// Prepare processes the build configuration parameters. func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "boot_command", }, }, }, raws...) if err != nil { return nil, err } // Accumulate any errors and warnings var errs *packer.MultiError errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.OutputConfig.Prepare(&b.config.ctx, &b.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(&b.config.ctx)...) warnings := make([]string, 0) err = b.checkDiskSize() if err != nil { errs = packer.MultiErrorAppend(errs, err) } err = b.checkRamSize() if err != nil { errs = packer.MultiErrorAppend(errs, err) } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } log.Println(fmt.Sprintf("%s: %v", "VMName", b.config.VMName)) if b.config.SwitchName == "" { // no switch name, try to get one attached to a online network adapter onlineSwitchName, err := hyperv.GetExternalOnlineVirtualSwitch() if onlineSwitchName == "" || err != nil { b.config.SwitchName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } else { b.config.SwitchName = onlineSwitchName } } if b.config.VlanId == "" { // b.config.VlanId = "1724" } if b.config.Cpu < 1 { b.config.Cpu = 1 } if b.config.Generation != 2 { b.config.Generation = 1 } if b.config.Generation == 2 { if len(b.config.FloppyFiles) > 0 { err = errors.New("Generation 2 vms don't support floppy drives. Use ISO image instead.") errs = packer.MultiErrorAppend(errs, err) } } log.Println(fmt.Sprintf("Using switch %s", b.config.SwitchName)) log.Println(fmt.Sprintf("%s: %v", "SwitchName", b.config.SwitchName)) log.Println(fmt.Sprintf("Using vlan %s", b.config.VlanId)) if b.config.Communicator == "" { b.config.Communicator = "ssh" } else if b.config.Communicator == "ssh" || b.config.Communicator == "winrm" { // good } else { err = errors.New("communicator must be either ssh or winrm") errs = packer.MultiErrorAppend(errs, err) } log.Println(fmt.Sprintf("%s: %v", "Communicator", b.config.Communicator)) // Errors if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if b.config.ISOChecksumType != "none" { if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } log.Println(fmt.Sprintf("%s: %v", "RawSingleISOUrl", b.config.RawSingleISOUrl)) // Warnings if b.config.ISOChecksumType == "none" { warnings = append(warnings, "A checksum type of 'none' was specified. Since ISO files are so big,\n"+ "a checksum is highly recommended.") } if b.config.ShutdownCommand == "" { warnings = append(warnings, "A shutdown_command was not specified. Without a shutdown command, Packer\n"+ "will forcibly halt the virtual machine, which may result in data loss.") } warning := b.checkHostAvailableMemory() if warning != "" { warnings = appendWarnings(warnings, warning) } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "boot_command", "tools_upload_path", }, }, }, raws...) if err != nil { return nil, err } // Accumulate any errors and warnings var errs *packer.MultiError errs = packer.MultiErrorAppend(errs, b.config.DriverConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.OutputConfig.Prepare(&b.config.ctx, &b.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.VMXConfig.Prepare(&b.config.ctx)...) warnings := make([]string, 0) if b.config.DiskName == "" { b.config.DiskName = "disk" } if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.DiskTypeId == "" { // Default is growable virtual disk split in 2GB files. b.config.DiskTypeId = "1" if b.config.RemoteType == "esx5" { b.config.DiskTypeId = "zeroedthick" } } if b.config.FloppyFiles == nil { b.config.FloppyFiles = make([]string, 0) } if b.config.GuestOSType == "" { b.config.GuestOSType = "other" } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } if b.config.Version == "" { b.config.Version = "9" } if b.config.RemoteUser == "" { b.config.RemoteUser = "******" } if b.config.RemoteDatastore == "" { b.config.RemoteDatastore = "datastore1" } if b.config.RemoteCacheDatastore == "" { b.config.RemoteCacheDatastore = b.config.RemoteDatastore } if b.config.RemoteCacheDirectory == "" { b.config.RemoteCacheDirectory = "packer_cache" } if b.config.RemotePort == 0 { b.config.RemotePort = 22 } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if b.config.ISOChecksumType != "none" { if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } if b.config.VMXTemplatePath != "" { if err := b.validateVMXTemplatePath(); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("vmx_template_path is invalid: %s", err)) } } // Remote configuration validation if b.config.RemoteType != "" { if b.config.RemoteHost == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("remote_host must be specified")) } } if b.config.Format != "" { if !(b.config.Format == "ova" || b.config.Format == "ovf" || b.config.Format == "vmx") { errs = packer.MultiErrorAppend(errs, fmt.Errorf("format must be one of ova, ovf, or vmx")) } } // Warnings if b.config.ISOChecksumType == "none" { warnings = append(warnings, "A checksum type of 'none' was specified. Since ISO files are so big,\n"+ "a checksum is highly recommended.") } if b.config.ShutdownCommand == "" { warnings = append(warnings, "A shutdown_command was not specified. Without a shutdown command, Packer\n"+ "will forcibly halt the virtual machine, which may result in data loss.") } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return nil, err } b.config.tpl, err = packer.NewConfigTemplate() if err != nil { return nil, err } b.config.tpl.UserVars = b.config.PackerUserVars // Accumulate any errors and warnings errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend( errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.PrlctlConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.PrlctlVersionConfig.Prepare(b.config.tpl)...) warnings := make([]string, 0) if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.ParallelsToolsMode == "" { b.config.ParallelsToolsMode = "upload" } if b.config.ParallelsToolsGuestPath == "" { b.config.ParallelsToolsGuestPath = "prl-tools.iso" } if b.config.ParallelsToolsHostPath == "" { b.config.ParallelsToolsHostPath = "/Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-other.iso" } if b.config.HardDriveInterface == "" { b.config.HardDriveInterface = "sata" } if b.config.GuestOSType == "" { b.config.GuestOSType = "other" } if b.config.GuestOSDistribution == "" { b.config.GuestOSDistribution = "other" } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if len(b.config.HostInterfaces) == 0 { b.config.HostInterfaces = []string{"en0", "en1", "en2", "en3", "en4", "en5", "en6", "en7", "en8", "en9", "ppp0", "ppp1", "ppp2"} } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } // Errors templates := map[string]*string{ "parallels_tools_mode": &b.config.ParallelsToolsMode, "parallels_tools_host_path": &b.config.ParallelsToolsHostPath, "parallels_tools_guest_path": &b.config.ParallelsToolsGuestPath, "guest_os_type": &b.config.GuestOSType, "guest_os_distribution": &b.config.GuestOSDistribution, "hard_drive_interface": &b.config.HardDriveInterface, "http_directory": &b.config.HTTPDir, "iso_checksum": &b.config.ISOChecksum, "iso_checksum_type": &b.config.ISOChecksumType, "iso_url": &b.config.RawSingleISOUrl, "vm_name": &b.config.VMName, } for n, ptr := range templates { var err error *ptr, err = b.config.tpl.Process(*ptr, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing %s: %s", n, err)) } } for i, url := range b.config.ISOUrls { var err error b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err)) } } validates := map[string]*string{ "parallels_tools_guest_path": &b.config.ParallelsToolsGuestPath, } for n, ptr := range validates { if err := b.config.tpl.Validate(*ptr); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error parsing %s: %s", n, err)) } } for i, command := range b.config.BootCommand { if err := b.config.tpl.Validate(command); err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing boot_command[%d]: %s", i, err)) } } if b.config.HardDriveInterface != "ide" && b.config.HardDriveInterface != "sata" && b.config.HardDriveInterface != "scsi" { errs = packer.MultiErrorAppend( errs, errors.New("hard_drive_interface can only be ide, sata, or scsi")) } if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if b.config.ISOChecksumType != "none" { if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } validMode := false validModes := []string{ parallelscommon.ParallelsToolsModeDisable, parallelscommon.ParallelsToolsModeAttach, parallelscommon.ParallelsToolsModeUpload, } for _, mode := range validModes { if b.config.ParallelsToolsMode == mode { validMode = true break } } if !validMode { errs = packer.MultiErrorAppend(errs, fmt.Errorf("parallels_tools_mode is invalid. Must be one of: %v", validModes)) } // Warnings if b.config.ISOChecksumType == "none" { warnings = append(warnings, "A checksum type of 'none' was specified. Since ISO files are so big,\n"+ "a checksum is highly recommended.") } if b.config.ShutdownCommand == "" { warnings = append(warnings, "A shutdown_command was not specified. Without a shutdown command, Packer\n"+ "will forcibly halt the virtual machine, which may result in data loss.") } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return nil, err } b.config.tpl, err = packer.NewConfigTemplate() if err != nil { return nil, err } b.config.tpl.UserVars = b.config.PackerUserVars // Accumulate any errors and warnings errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend( errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.PrlctlConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.PrlctlVersionConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.WinRMConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(b.config.tpl)...) warnings := make([]string, 0) if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.HardDriveInterface == "" { b.config.HardDriveInterface = "sata" } if b.config.GuestOSType == "" { b.config.GuestOSType = "other" } if b.config.GuestOSDistribution != "" { // Compatibility with older templates: // Use value of 'guest_os_distribution' if it is defined. b.config.GuestOSType = b.config.GuestOSDistribution warnings = append(warnings, "A 'guest_os_distribution' has been completely replaced with 'guest_os_type'\n"+ "It is recommended to remove it and assign the previous value to 'guest_os_type'.\n"+ "Run it to see all available values: `prlctl create x -d list` ") } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if len(b.config.HostInterfaces) == 0 { b.config.HostInterfaces = []string{"en0", "en1", "en2", "en3", "en4", "en5", "en6", "en7", "en8", "en9", "ppp0", "ppp1", "ppp2"} } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } // Errors templates := map[string]*string{ "guest_os_type": &b.config.GuestOSType, "hard_drive_interface": &b.config.HardDriveInterface, "http_directory": &b.config.HTTPDir, "iso_checksum": &b.config.ISOChecksum, "iso_checksum_type": &b.config.ISOChecksumType, "iso_url": &b.config.RawSingleISOUrl, "vm_name": &b.config.VMName, } for n, ptr := range templates { var err error *ptr, err = b.config.tpl.Process(*ptr, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing %s: %s", n, err)) } } for i, url := range b.config.ISOUrls { var err error b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err)) } } for i, command := range b.config.BootCommand { if err := b.config.tpl.Validate(command); err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing boot_command[%d]: %s", i, err)) } } if b.config.HardDriveInterface != "ide" && b.config.HardDriveInterface != "sata" && b.config.HardDriveInterface != "scsi" { errs = packer.MultiErrorAppend( errs, errors.New("hard_drive_interface can only be ide, sata, or scsi")) } if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if b.config.ISOChecksumType != "none" { if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } // Warnings if b.config.ISOChecksumType == "none" { warnings = append(warnings, "A checksum type of 'none' was specified. Since ISO files are so big,\n"+ "a checksum is highly recommended.") } if b.config.ShutdownCommand == "" { warnings = append(warnings, "A shutdown_command was not specified. Without a shutdown command, Packer\n"+ "will forcibly halt the virtual machine, which may result in data loss.") } if b.config.ParallelsToolsHostPath != "" { warnings = append(warnings, "A 'parallels_tools_host_path' has been deprecated and not in use anymore\n"+ "You can remove it from your Packer template.") } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return nil, err } b.config.tpl, err = packer.NewConfigTemplate() if err != nil { return nil, err } b.config.tpl.UserVars = b.config.PackerUserVars // Accumulate any errors errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend(errs, b.config.DriverConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.VMXConfig.Prepare(b.config.tpl)...) warnings := make([]string, 0) if b.config.DiskName == "" { b.config.DiskName = "disk" } if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.DiskTypeId == "" { // Default is growable virtual disk split in 2GB files. b.config.DiskTypeId = "1" if b.config.RemoteType == "esx5" { b.config.DiskTypeId = "zeroedthick" } } if b.config.FloppyFiles == nil { b.config.FloppyFiles = make([]string, 0) } if b.config.GuestOSType == "" { b.config.GuestOSType = "other" } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if b.config.VNCPortMin == 0 { b.config.VNCPortMin = 5900 } if b.config.VNCPortMax == 0 { b.config.VNCPortMax = 6000 } if b.config.RemoteUser == "" { b.config.RemoteUser = "******" } if b.config.RemoteDatastore == "" { b.config.RemoteDatastore = "datastore1" } if b.config.RemotePort == 0 { b.config.RemotePort = 22 } // Errors templates := map[string]*string{ "disk_name": &b.config.DiskName, "guest_os_type": &b.config.GuestOSType, "http_directory": &b.config.HTTPDir, "iso_checksum": &b.config.ISOChecksum, "iso_checksum_type": &b.config.ISOChecksumType, "iso_url": &b.config.RawSingleISOUrl, "vm_name": &b.config.VMName, "vmx_template_path": &b.config.VMXTemplatePath, "remote_type": &b.config.RemoteType, "remote_host": &b.config.RemoteHost, "remote_datastore": &b.config.RemoteDatastore, "remote_user": &b.config.RemoteUser, "remote_password": &b.config.RemotePassword, } for n, ptr := range templates { var err error *ptr, err = b.config.tpl.Process(*ptr, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing %s: %s", n, err)) } } for i, url := range b.config.ISOUrls { var err error b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err)) } } for i, command := range b.config.BootCommand { if err := b.config.tpl.Validate(command); err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing boot_command[%d]: %s", i, err)) } } for i, file := range b.config.FloppyFiles { var err error b.config.FloppyFiles[i], err = b.config.tpl.Process(file, nil) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing floppy_files[%d]: %s", i, err)) } } if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if b.config.ISOChecksumType != "none" { if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } if b.config.VMXTemplatePath != "" { if err := b.validateVMXTemplatePath(); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("vmx_template_path is invalid: %s", err)) } } if b.config.VNCPortMin > b.config.VNCPortMax { errs = packer.MultiErrorAppend( errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max")) } // Remote configuration validation if b.config.RemoteType != "" { if b.config.RemoteHost == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("remote_host must be specified")) } } // Warnings if b.config.ISOChecksumType == "none" { warnings = append(warnings, "A checksum type of 'none' was specified. Since ISO files are so big,\n"+ "a checksum is highly recommended.") } if b.config.ShutdownCommand == "" { warnings = append(warnings, "A shutdown_command was not specified. Without a shutdown command, Packer\n"+ "will forcibly halt the virtual machine, which may result in data loss.") } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }
func (b *Builder) Prepare(raws ...interface{}) error { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return err } // Accumulate any errors errs := common.CheckUnusedConfig(md) if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.FloppyFiles == nil { b.config.FloppyFiles = make([]string, 0) } if b.config.GuestAdditionsPath == "" { b.config.GuestAdditionsPath = "VBoxGuestAdditions.iso" } if b.config.GuestOSType == "" { b.config.GuestOSType = "Other" } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if b.config.OutputDir == "" { b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName) } if b.config.RawBootWait == "" { b.config.RawBootWait = "10s" } if b.config.SSHHostPortMin == 0 { b.config.SSHHostPortMin = 2222 } if b.config.SSHHostPortMax == 0 { b.config.SSHHostPortMax = 4444 } if b.config.SSHPort == 0 { b.config.SSHPort = 22 } if b.config.VBoxManage == nil { b.config.VBoxManage = make([][]string, 0) } if b.config.VBoxVersionFile == "" { b.config.VBoxVersionFile = ".vbox_version" } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } if b.config.ISOUrl == "" { errs = packer.MultiErrorAppend( errs, errors.New("An iso_url must be specified.")) } else { b.config.ISOUrl, err = common.DownloadableURL(b.config.ISOUrl) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("iso_url: %s", err)) } } if b.config.GuestAdditionsSHA256 != "" { b.config.GuestAdditionsSHA256 = strings.ToLower(b.config.GuestAdditionsSHA256) } if b.config.GuestAdditionsURL != "" { b.config.GuestAdditionsURL, err = common.DownloadableURL(b.config.GuestAdditionsURL) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("guest_additions_url: %s", err)) } } if !b.config.PackerForce { if _, err := os.Stat(b.config.OutputDir); err == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Output directory '%s' already exists. It must not exist.", b.config.OutputDir)) } } b.config.bootWait, err = time.ParseDuration(b.config.RawBootWait) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) } if b.config.RawShutdownTimeout == "" { b.config.RawShutdownTimeout = "5m" } if b.config.RawSSHWaitTimeout == "" { b.config.RawSSHWaitTimeout = "20m" } b.config.shutdownTimeout, err = time.ParseDuration(b.config.RawShutdownTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err)) } if b.config.SSHHostPortMin > b.config.SSHHostPortMax { errs = packer.MultiErrorAppend( errs, errors.New("ssh_host_port_min must be less than ssh_host_port_max")) } if b.config.SSHUser == "" { errs = packer.MultiErrorAppend( errs, errors.New("An ssh_username must be specified.")) } b.config.sshWaitTimeout, err = time.ParseDuration(b.config.RawSSHWaitTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing ssh_wait_timeout: %s", err)) } b.driver, err = b.newDriver() if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed creating VirtualBox driver: %s", err)) } if errs != nil && len(errs.Errors) > 0 { return errs } return nil }
func (s *stepDownloadGuestAdditions) Run(state multistep.StateBag) multistep.StepAction { var action multistep.StepAction driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) config := state.Get("config").(*config) // If we've disabled guest additions, don't download if config.GuestAdditionsMode == GuestAdditionsModeDisable { log.Println("Not downloading guest additions since it is disabled.") return multistep.ActionContinue } // Get VBox version version, err := driver.Version() if err != nil { state.Put("error", fmt.Errorf("Error reading version for guest additions download: %s", err)) return multistep.ActionHalt } if newVersion, ok := additionsVersionMap[version]; ok { log.Printf("Rewriting guest additions version: %s to %s", version, newVersion) version = newVersion } additionsName := fmt.Sprintf("VBoxGuestAdditions_%s.iso", version) // Use provided version or get it from virtualbox.org var checksum string if config.GuestAdditionsSHA256 != "" { checksum = config.GuestAdditionsSHA256 } else { checksum, action = s.downloadAdditionsSHA256(state, version, additionsName) if action != multistep.ActionContinue { return action } } // Use the provided source (URL or file path) or generate it url := config.GuestAdditionsURL if url != "" { tplData := &guestAdditionsUrlTemplate{ Version: version, } url, err = config.tpl.Process(url, tplData) if err != nil { err := fmt.Errorf("Error preparing guest additions url: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } } else { url = fmt.Sprintf( "http://download.virtualbox.org/virtualbox/%s/%s", version, additionsName) } url, err = common.DownloadableURL(url) if err != nil { err := fmt.Errorf("Error preparing guest additions url: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } log.Printf("Guest additions URL: %s", url) downStep := &common.StepDownload{ Checksum: checksum, ChecksumType: "sha256", Description: "Guest additions", ResultKey: "guest_additions_path", Url: []string{url}, } return downStep.Run(state) }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "boot_command", "qemuargs", }, }, }, raws...) if err != nil { return nil, err } var errs *packer.MultiError warnings := make([]string, 0) if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.DiskCache == "" { b.config.DiskCache = "writeback" } if b.config.DiskDiscard == "" { b.config.DiskDiscard = "ignore" } if b.config.Accelerator == "" { b.config.Accelerator = "kvm" } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if b.config.MachineType == "" { b.config.MachineType = "pc" } if b.config.OutputDir == "" { b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName) } if b.config.QemuBinary == "" { b.config.QemuBinary = "qemu-system-x86_64" } if b.config.RawBootWait == "" { b.config.RawBootWait = "10s" } if b.config.SSHHostPortMin == 0 { b.config.SSHHostPortMin = 2222 } if b.config.SSHHostPortMax == 0 { b.config.SSHHostPortMax = 4444 } if b.config.SSHPort == 0 { b.config.SSHPort = 22 } if b.config.VNCPortMin == 0 { b.config.VNCPortMin = 5900 } if b.config.VNCPortMax == 0 { b.config.VNCPortMax = 6000 } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } if b.config.Format == "" { b.config.Format = "qcow2" } if b.config.FloppyFiles == nil { b.config.FloppyFiles = make([]string, 0) } if b.config.NetDevice == "" { b.config.NetDevice = "virtio-net" } if b.config.DiskInterface == "" { b.config.DiskInterface = "virtio" } if !(b.config.Format == "qcow2" || b.config.Format == "raw") { errs = packer.MultiErrorAppend( errs, errors.New("invalid format, only 'qcow2' or 'raw' are allowed")) } if _, ok := accels[b.config.Accelerator]; !ok { errs = packer.MultiErrorAppend( errs, errors.New("invalid accelerator, only 'kvm', 'tcg', 'xen', or 'none' are allowed")) } if _, ok := netDevice[b.config.NetDevice]; !ok { errs = packer.MultiErrorAppend( errs, errors.New("unrecognized network device type")) } if _, ok := diskInterface[b.config.DiskInterface]; !ok { errs = packer.MultiErrorAppend( errs, errors.New("unrecognized disk interface type")) } if _, ok := diskCache[b.config.DiskCache]; !ok { errs = packer.MultiErrorAppend( errs, errors.New("unrecognized disk cache type")) } if _, ok := diskDiscard[b.config.DiskDiscard]; !ok { errs = packer.MultiErrorAppend( errs, errors.New("unrecognized disk cache type")) } if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if b.config.ISOChecksumType != "none" { if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } if !b.config.PackerForce { if _, err := os.Stat(b.config.OutputDir); err == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Output directory '%s' already exists. It must not exist.", b.config.OutputDir)) } } b.config.bootWait, err = time.ParseDuration(b.config.RawBootWait) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) } if b.config.RawShutdownTimeout == "" { b.config.RawShutdownTimeout = "5m" } if b.config.RawSSHWaitTimeout == "" { b.config.RawSSHWaitTimeout = "20m" } b.config.shutdownTimeout, err = time.ParseDuration(b.config.RawShutdownTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err)) } if b.config.SSHKeyPath != "" { if _, err := os.Stat(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } else if _, err := commonssh.FileSigner(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } } if b.config.SSHHostPortMin > b.config.SSHHostPortMax { errs = packer.MultiErrorAppend( errs, errors.New("ssh_host_port_min must be less than ssh_host_port_max")) } if b.config.SSHUser == "" { errs = packer.MultiErrorAppend( errs, errors.New("An ssh_username must be specified.")) } b.config.sshWaitTimeout, err = time.ParseDuration(b.config.RawSSHWaitTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing ssh_wait_timeout: %s", err)) } if b.config.VNCPortMin > b.config.VNCPortMax { errs = packer.MultiErrorAppend( errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max")) } if b.config.QemuArgs == nil { b.config.QemuArgs = make([][]string, 0) } if b.config.ISOChecksumType == "none" { warnings = append(warnings, "A checksum type of 'none' was specified. Since ISO files are so big,\n"+ "a checksum is highly recommended.") } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }
func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error) { md, err := common.DecodeConfig(&self.config, raws...) if err != nil { return nil, err } self.config.tpl, err = packer.NewConfigTemplate() if err != nil { return nil, err } self.config.tpl.UserVars = self.config.PackerUserVars errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend( errs, self.config.CommonConfig.Prepare(self.config.tpl, &self.config.PackerConfig)...) // Set default values if self.config.RawInstallTimeout == "" { self.config.RawInstallTimeout = "200m" } if self.config.DiskSize == 0 { self.config.DiskSize = 40000 } if self.config.VMMemory == 0 { self.config.VMMemory = 1024 } if self.config.CloneTemplate == "" { self.config.CloneTemplate = "Other install media" } if len(self.config.PlatformArgs) == 0 { pargs := make(map[string]string) pargs["viridian"] = "false" pargs["nx"] = "true" pargs["pae"] = "true" pargs["apic"] = "true" pargs["timeoffset"] = "0" pargs["acpi"] = "1" self.config.PlatformArgs = pargs } // Template substitution templates := map[string]*string{ "clone_template": &self.config.CloneTemplate, "network_name": &self.config.NetworkName, "iso_checksum": &self.config.ISOChecksum, "iso_checksum_type": &self.config.ISOChecksumType, "iso_url": &self.config.ISOUrl, "iso_name": &self.config.ISOName, "install_timeout": &self.config.RawInstallTimeout, } for i := range self.config.ISOUrls { templates[fmt.Sprintf("iso_urls[%d]", i)] = &self.config.ISOUrls[i] } for n, ptr := range templates { var err error *ptr, err = self.config.tpl.Process(*ptr, nil) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing %s: %s", n, err)) } } // Validation self.config.InstallTimeout, err = time.ParseDuration(self.config.RawInstallTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse install_timeout: %s", err)) } if self.config.ISOName == "" { // If ISO name is not specified, assume a URL and checksum has been provided. if self.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { self.config.ISOChecksumType = strings.ToLower(self.config.ISOChecksumType) if self.config.ISOChecksumType != "none" { if self.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to the file size being large, an iso_checksum is required.")) } else { self.config.ISOChecksum = strings.ToLower(self.config.ISOChecksum) } if hash := common.HashForType(self.config.ISOChecksumType); hash == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", self.config.ISOChecksumType)) } } } if len(self.config.ISOUrls) == 0 { if self.config.ISOUrl == "" { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else { self.config.ISOUrls = []string{self.config.ISOUrl} } } else if self.config.ISOUrl != "" { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } for i, url := range self.config.ISOUrls { self.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_urls[%d]: %s", i, err)) } } } else { // An ISO name has been provided. It should be attached from an available SR. } if len(errs.Errors) > 0 { retErr = errors.New(errs.Error()) } return nil, retErr }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return nil, err } b.config.tpl, err = packer.NewConfigTemplate() if err != nil { return nil, err } b.config.tpl.UserVars = b.config.PackerUserVars // Accumulate any errors and warnings errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend(errs, b.config.ExportConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend( errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.VBoxManageConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.VBoxVersionConfig.Prepare(b.config.tpl)...) warnings := make([]string, 0) if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.GuestAdditionsMode == "" { b.config.GuestAdditionsMode = "upload" } if b.config.GuestAdditionsPath == "" { b.config.GuestAdditionsPath = "VBoxGuestAdditions.iso" } if b.config.HardDriveInterface == "" { b.config.HardDriveInterface = "ide" } if b.config.GuestOSType == "" { b.config.GuestOSType = "Other" } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } // Errors templates := map[string]*string{ "guest_additions_mode": &b.config.GuestAdditionsMode, "guest_additions_sha256": &b.config.GuestAdditionsSHA256, "guest_os_type": &b.config.GuestOSType, "hard_drive_interface": &b.config.HardDriveInterface, "http_directory": &b.config.HTTPDir, "iso_checksum": &b.config.ISOChecksum, "iso_checksum_type": &b.config.ISOChecksumType, "iso_url": &b.config.RawSingleISOUrl, "vm_name": &b.config.VMName, } for n, ptr := range templates { var err error *ptr, err = b.config.tpl.Process(*ptr, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing %s: %s", n, err)) } } for i, url := range b.config.ISOUrls { var err error b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err)) } } validates := map[string]*string{ "guest_additions_path": &b.config.GuestAdditionsPath, "guest_additions_url": &b.config.GuestAdditionsURL, } for n, ptr := range validates { if err := b.config.tpl.Validate(*ptr); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error parsing %s: %s", n, err)) } } for i, command := range b.config.BootCommand { if err := b.config.tpl.Validate(command); err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing boot_command[%d]: %s", i, err)) } } if b.config.HardDriveInterface != "ide" && b.config.HardDriveInterface != "sata" { errs = packer.MultiErrorAppend( errs, errors.New("hard_drive_interface can only be ide or sata")) } if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } validMode := false validModes := []string{ GuestAdditionsModeDisable, GuestAdditionsModeAttach, GuestAdditionsModeUpload, } for _, mode := range validModes { if b.config.GuestAdditionsMode == mode { validMode = true break } } if !validMode { errs = packer.MultiErrorAppend(errs, fmt.Errorf("guest_additions_mode is invalid. Must be one of: %v", validModes)) } if b.config.GuestAdditionsSHA256 != "" { b.config.GuestAdditionsSHA256 = strings.ToLower(b.config.GuestAdditionsSHA256) } // Warnings if b.config.ShutdownCommand == "" { warnings = append(warnings, "A shutdown_command was not specified. Without a shutdown command, Packer\n"+ "will forcibly halt the virtual machine, which may result in data loss.") } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return nil, err } b.config.tpl, err = packer.NewConfigTemplate() if err != nil { return nil, err } b.config.tpl.UserVars = b.config.PackerUserVars // Accumulate any errors errs := common.CheckUnusedConfig(md) if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.Accelerator == "" { b.config.Accelerator = "kvm" } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if b.config.OutputDir == "" { b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName) } if b.config.RawBootWait == "" { b.config.RawBootWait = "10s" } if b.config.SSHHostPortMin == 0 { b.config.SSHHostPortMin = 2222 } if b.config.SSHHostPortMax == 0 { b.config.SSHHostPortMax = 4444 } if b.config.SSHPort == 0 { b.config.SSHPort = 22 } if b.config.VNCPortMin == 0 { b.config.VNCPortMin = 5900 } if b.config.VNCPortMax == 0 { b.config.VNCPortMax = 6000 } for i, args := range b.config.QemuArgs { for j, arg := range args { if err := b.config.tpl.Validate(arg); err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing qemu-system_x86-64[%d][%d]: %s", i, j, err)) } } } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } if b.config.Format == "" { b.config.Format = "qcow2" } if b.config.FloppyFiles == nil { b.config.FloppyFiles = make([]string, 0) } if b.config.NetDevice == "" { b.config.NetDevice = "virtio-net" } if b.config.DiskInterface == "" { b.config.DiskInterface = "virtio" } // Errors templates := map[string]*string{ "http_directory": &b.config.HTTPDir, "iso_checksum": &b.config.ISOChecksum, "iso_checksum_type": &b.config.ISOChecksumType, "iso_url": &b.config.RawSingleISOUrl, "output_directory": &b.config.OutputDir, "shutdown_command": &b.config.ShutdownCommand, "ssh_password": &b.config.SSHPassword, "ssh_username": &b.config.SSHUser, "vm_name": &b.config.VMName, "format": &b.config.Format, "boot_wait": &b.config.RawBootWait, "shutdown_timeout": &b.config.RawShutdownTimeout, "ssh_wait_timeout": &b.config.RawSSHWaitTimeout, "accelerator": &b.config.Accelerator, "net_device": &b.config.NetDevice, "disk_interface": &b.config.DiskInterface, } for n, ptr := range templates { var err error *ptr, err = b.config.tpl.Process(*ptr, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing %s: %s", n, err)) } } for i, url := range b.config.ISOUrls { var err error b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err)) } } for i, command := range b.config.BootCommand { if err := b.config.tpl.Validate(command); err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing boot_command[%d]: %s", i, err)) } } for i, file := range b.config.FloppyFiles { var err error b.config.FloppyFiles[i], err = b.config.tpl.Process(file, nil) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing floppy_files[%d]: %s", i, err)) } } if !(b.config.Format == "qcow2" || b.config.Format == "raw") { errs = packer.MultiErrorAppend( errs, errors.New("invalid format, only 'qcow2' or 'raw' are allowed")) } if !(b.config.Accelerator == "kvm" || b.config.Accelerator == "xen") { errs = packer.MultiErrorAppend( errs, errors.New("invalid format, only 'kvm' or 'xen' are allowed")) } if _, ok := netDevice[b.config.NetDevice]; !ok { errs = packer.MultiErrorAppend( errs, errors.New("unrecognized network device type")) } if _, ok := diskInterface[b.config.DiskInterface]; !ok { errs = packer.MultiErrorAppend( errs, errors.New("unrecognized disk interface type")) } if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } if !b.config.PackerForce { if _, err := os.Stat(b.config.OutputDir); err == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Output directory '%s' already exists. It must not exist.", b.config.OutputDir)) } } b.config.bootWait, err = time.ParseDuration(b.config.RawBootWait) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) } if b.config.RawShutdownTimeout == "" { b.config.RawShutdownTimeout = "5m" } if b.config.RawSSHWaitTimeout == "" { b.config.RawSSHWaitTimeout = "20m" } b.config.shutdownTimeout, err = time.ParseDuration(b.config.RawShutdownTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err)) } if b.config.SSHKeyPath != "" { if _, err := os.Stat(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } else if _, err := sshKeyToKeyring(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } } if b.config.SSHHostPortMin > b.config.SSHHostPortMax { errs = packer.MultiErrorAppend( errs, errors.New("ssh_host_port_min must be less than ssh_host_port_max")) } if b.config.SSHUser == "" { errs = packer.MultiErrorAppend( errs, errors.New("An ssh_username must be specified.")) } b.config.sshWaitTimeout, err = time.ParseDuration(b.config.RawSSHWaitTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing ssh_wait_timeout: %s", err)) } if b.config.VNCPortMin > b.config.VNCPortMax { errs = packer.MultiErrorAppend( errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max")) } if b.config.QemuArgs == nil { b.config.QemuArgs = make([][]string, 0) } if errs != nil && len(errs.Errors) > 0 { return nil, errs } return nil, nil }
func (s *StepDownloadGuestAdditions) Run(state multistep.StateBag) multistep.StepAction { var action multistep.StepAction driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) // If we've disabled guest additions, don't download if s.GuestAdditionsMode == GuestAdditionsModeDisable { log.Println("Not downloading guest additions since it is disabled.") return multistep.ActionContinue } // Get VBox version version, err := driver.Version() if err != nil { state.Put("error", fmt.Errorf("Error reading version for guest additions download: %s", err)) return multistep.ActionHalt } if newVersion, ok := additionsVersionMap[version]; ok { log.Printf("Rewriting guest additions version: %s to %s", version, newVersion) version = newVersion } additionsName := fmt.Sprintf("VBoxGuestAdditions_%s.iso", version) // Use provided version or get it from virtualbox.org var checksum string checksumType := "sha256" // Use the provided source (URL or file path) or generate it url := s.GuestAdditionsURL if url != "" { s.Ctx.Data = &guestAdditionsUrlTemplate{ Version: version, } url, err = interpolate.Render(url, &s.Ctx) if err != nil { err := fmt.Errorf("Error preparing guest additions url: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } } else { url, err = driver.Iso() if err == nil { checksumType = "none" } else { ui.Error(err.Error()) url = fmt.Sprintf( "http://download.virtualbox.org/virtualbox/%s/%s", version, additionsName) } } if url == "" { err := fmt.Errorf("Couldn't detect guest additions URL.\n" + "Please specify `guest_additions_url` manually.") state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } if checksumType != "none" { if s.GuestAdditionsSHA256 != "" { checksum = s.GuestAdditionsSHA256 } else { checksum, action = s.downloadAdditionsSHA256(state, version, additionsName) if action != multistep.ActionContinue { return action } } } url, err = common.DownloadableURL(url) if err != nil { err := fmt.Errorf("Error preparing guest additions url: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } log.Printf("Guest additions URL: %s", url) downStep := &common.StepDownload{ Checksum: checksum, ChecksumType: checksumType, Description: "Guest additions", ResultKey: "guest_additions_path", Url: []string{url}, } return downStep.Run(state) }
func (b *Builder) Prepare(raws ...interface{}) error { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return err } // Accumulate any errors errs := common.CheckUnusedConfig(md) if b.config.DiskName == "" { b.config.DiskName = "disk" } if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.FloppyFiles == nil { b.config.FloppyFiles = make([]string, 0) } if b.config.GuestOSType == "" { b.config.GuestOSType = "other" } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if b.config.RawBootWait == "" { b.config.RawBootWait = "10s" } if b.config.VNCPortMin == 0 { b.config.VNCPortMin = 5900 } if b.config.VNCPortMax == 0 { b.config.VNCPortMax = 6000 } if b.config.OutputDir == "" { b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName) } if b.config.SSHPort == 0 { b.config.SSHPort = 22 } if b.config.ToolsUploadPath == "" { b.config.ToolsUploadPath = "{{ .Flavor }}.iso" } if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } if b.config.ISOUrl == "" { errs = packer.MultiErrorAppend( errs, errors.New("An iso_url must be specified.")) } else { b.config.ISOUrl, err = common.DownloadableURL(b.config.ISOUrl) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("iso_url: %s", err)) } } if !b.config.PackerForce { if _, err := os.Stat(b.config.OutputDir); err == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Output directory '%s' already exists. It must not exist.", b.config.OutputDir)) } } if b.config.SSHUser == "" { errs = packer.MultiErrorAppend( errs, errors.New("An ssh_username must be specified.")) } if b.config.RawBootWait != "" { b.config.bootWait, err = time.ParseDuration(b.config.RawBootWait) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) } } if b.config.RawShutdownTimeout == "" { b.config.RawShutdownTimeout = "5m" } b.config.shutdownTimeout, err = time.ParseDuration(b.config.RawShutdownTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err)) } if b.config.RawSSHWaitTimeout == "" { b.config.RawSSHWaitTimeout = "20m" } b.config.sshWaitTimeout, err = time.ParseDuration(b.config.RawSSHWaitTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing ssh_wait_timeout: %s", err)) } if _, err := template.New("path").Parse(b.config.ToolsUploadPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("tools_upload_path invalid: %s", err)) } if b.config.VNCPortMin > b.config.VNCPortMax { errs = packer.MultiErrorAppend( errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max")) } b.driver, err = NewDriver() if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed creating VMware driver: %s", err)) } if errs != nil && len(errs.Errors) > 0 { return errs } return nil }
func NewConfig(raws ...interface{}) (*Config, []string, error) { c := new(Config) err := config.Decode(c, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &c.ctx, InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "boot_command", "guest_additions_path", "guest_additions_url", "vboxmanage", "vboxmanage_post", }, }, }, raws...) if err != nil { return nil, nil, err } // Defaults if c.GuestAdditionsMode == "" { c.GuestAdditionsMode = "upload" } if c.GuestAdditionsPath == "" { c.GuestAdditionsPath = "VBoxGuestAdditions.iso" } if c.VMName == "" { c.VMName = fmt.Sprintf( "packer-%s-%d", c.PackerBuildName, interpolate.InitTime.Unix()) } // Prepare the errors var errs *packer.MultiError errs = packer.MultiErrorAppend(errs, c.ExportConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.ExportOpts.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(&c.ctx, &c.PackerConfig)...) errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.VBoxManageConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.VBoxManagePostConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.VBoxVersionConfig.Prepare(&c.ctx)...) c.ChecksumType = strings.ToLower(c.ChecksumType) c.Checksum = strings.ToLower(c.Checksum) if c.SourcePath == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required")) } else { c.SourcePath, err = common.DownloadableURL(c.SourcePath) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is invalid: %s", err)) } } validMode := false validModes := []string{ vboxcommon.GuestAdditionsModeDisable, vboxcommon.GuestAdditionsModeAttach, vboxcommon.GuestAdditionsModeUpload, } for _, mode := range validModes { if c.GuestAdditionsMode == mode { validMode = true break } } if !validMode { errs = packer.MultiErrorAppend(errs, fmt.Errorf("guest_additions_mode is invalid. Must be one of: %v", validModes)) } if c.GuestAdditionsSHA256 != "" { c.GuestAdditionsSHA256 = strings.ToLower(c.GuestAdditionsSHA256) } // Warnings var warnings []string if c.ShutdownCommand == "" { warnings = append(warnings, "A shutdown_command was not specified. Without a shutdown command, Packer\n"+ "will forcibly halt the virtual machine, which may result in data loss.") } // Check for any errors. if errs != nil && len(errs.Errors) > 0 { return nil, warnings, errs } // TODO: Write a packer fix and just remove import_opts if c.ImportOpts != "" { c.ImportFlags = append(c.ImportFlags, "--options", c.ImportOpts) } return c, warnings, nil }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return nil, err } b.config.tpl, err = packer.NewConfigTemplate() if err != nil { return nil, err } b.config.tpl.UserVars = b.config.PackerUserVars // Accumulate any errors errs := common.CheckUnusedConfig(md) warnings := make([]string, 0) if b.config.DiskName == "" { b.config.DiskName = "disk" } if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.DiskTypeId == "" { // Default is growable virtual disk split in 2GB files. b.config.DiskTypeId = "1" if b.config.RemoteType == "esx5" { b.config.DiskTypeId = "zeroedthick" } } if b.config.FloppyFiles == nil { b.config.FloppyFiles = make([]string, 0) } if b.config.GuestOSType == "" { b.config.GuestOSType = "other" } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if b.config.RawBootWait == "" { b.config.RawBootWait = "10s" } if b.config.VNCPortMin == 0 { b.config.VNCPortMin = 5900 } if b.config.VNCPortMax == 0 { b.config.VNCPortMax = 6000 } if b.config.OutputDir == "" { b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName) } if b.config.RemoteUser == "" { b.config.RemoteUser = "******" } if b.config.RemoteDatastore == "" { b.config.RemoteDatastore = "datastore1" } if b.config.RemotePort == 0 { b.config.RemotePort = 22 } if b.config.SSHPort == 0 { b.config.SSHPort = 22 } if b.config.ToolsUploadPath == "" { b.config.ToolsUploadPath = "{{ .Flavor }}.iso" } // Errors templates := map[string]*string{ "disk_name": &b.config.DiskName, "guest_os_type": &b.config.GuestOSType, "http_directory": &b.config.HTTPDir, "iso_checksum": &b.config.ISOChecksum, "iso_checksum_type": &b.config.ISOChecksumType, "iso_url": &b.config.RawSingleISOUrl, "output_directory": &b.config.OutputDir, "shutdown_command": &b.config.ShutdownCommand, "ssh_key_path": &b.config.SSHKeyPath, "ssh_password": &b.config.SSHPassword, "ssh_username": &b.config.SSHUser, "tools_upload_flavor": &b.config.ToolsUploadFlavor, "vm_name": &b.config.VMName, "boot_wait": &b.config.RawBootWait, "shutdown_timeout": &b.config.RawShutdownTimeout, "ssh_wait_timeout": &b.config.RawSSHWaitTimeout, "vmx_template_path": &b.config.VMXTemplatePath, "remote_type": &b.config.RemoteType, "remote_host": &b.config.RemoteHost, "remote_datastore": &b.config.RemoteDatastore, "remote_user": &b.config.RemoteUser, "remote_password": &b.config.RemotePassword, } for n, ptr := range templates { var err error *ptr, err = b.config.tpl.Process(*ptr, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing %s: %s", n, err)) } } for i, url := range b.config.ISOUrls { var err error b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err)) } } for i, command := range b.config.BootCommand { if err := b.config.tpl.Validate(command); err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing boot_command[%d]: %s", i, err)) } } for i, file := range b.config.FloppyFiles { var err error b.config.FloppyFiles[i], err = b.config.tpl.Process(file, nil) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing floppy_files[%d]: %s", i, err)) } } newVMXData := make(map[string]string) for k, v := range b.config.VMXData { k, err = b.config.tpl.Process(k, nil) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing VMX data key %s: %s", k, err)) continue } v, err = b.config.tpl.Process(v, nil) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing VMX data value '%s': %s", v, err)) continue } newVMXData[k] = v } b.config.VMXData = newVMXData if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } if !b.config.PackerForce { if _, err := os.Stat(b.config.OutputDir); err == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Output directory '%s' already exists. It must not exist.", b.config.OutputDir)) } } if b.config.SSHKeyPath != "" { if _, err := os.Stat(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } else if _, err := sshKeyToKeyring(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } } if b.config.SSHUser == "" { errs = packer.MultiErrorAppend( errs, errors.New("An ssh_username must be specified.")) } if b.config.RawBootWait != "" { b.config.bootWait, err = time.ParseDuration(b.config.RawBootWait) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) } } if b.config.RawShutdownTimeout == "" { b.config.RawShutdownTimeout = "5m" } b.config.shutdownTimeout, err = time.ParseDuration(b.config.RawShutdownTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err)) } if b.config.RawSSHWaitTimeout == "" { b.config.RawSSHWaitTimeout = "20m" } b.config.sshWaitTimeout, err = time.ParseDuration(b.config.RawSSHWaitTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing ssh_wait_timeout: %s", err)) } if _, err := template.New("path").Parse(b.config.ToolsUploadPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("tools_upload_path invalid: %s", err)) } if b.config.VMXTemplatePath != "" { if err := b.validateVMXTemplatePath(); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("vmx_template_path is invalid: %s", err)) } } if b.config.VNCPortMin > b.config.VNCPortMax { errs = packer.MultiErrorAppend( errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max")) } // Remote configuration validation if b.config.RemoteType != "" { if b.config.RemoteHost == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("remote_host must be specified")) } } // Warnings if b.config.ShutdownCommand == "" { warnings = append(warnings, "A shutdown_command was not specified. Without a shutdown command, Packer\n"+ "will forcibly halt the virtual machine, which may result in data loss.") } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }
func (b *Builder) Prepare(raws ...interface{}) error { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return err } b.config.tpl, err = packer.NewConfigTemplate() if err != nil { return err } b.config.tpl.UserVars = b.config.PackerUserVars // Accumulate any errors errs := common.CheckUnusedConfig(md) if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.FloppyFiles == nil { b.config.FloppyFiles = make([]string, 0) } if b.config.GuestAdditionsPath == "" { b.config.GuestAdditionsPath = "VBoxGuestAdditions.iso" } if b.config.HardDriveInterface == "" { b.config.HardDriveInterface = "ide" } if b.config.GuestOSType == "" { b.config.GuestOSType = "Other" } if b.config.HTTPPortMin == 0 { b.config.HTTPPortMin = 8000 } if b.config.HTTPPortMax == 0 { b.config.HTTPPortMax = 9000 } if b.config.OutputDir == "" { b.config.OutputDir = fmt.Sprintf("output-%s", b.config.PackerBuildName) } if b.config.RawBootWait == "" { b.config.RawBootWait = "10s" } if b.config.SSHHostPortMin == 0 { b.config.SSHHostPortMin = 2222 } if b.config.SSHHostPortMax == 0 { b.config.SSHHostPortMax = 4444 } if b.config.SSHPort == 0 { b.config.SSHPort = 22 } if b.config.VBoxManage == nil { b.config.VBoxManage = make([][]string, 0) } if b.config.VBoxVersionFile == "" { b.config.VBoxVersionFile = ".vbox_version" } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } if b.config.Format == "" { b.config.Format = "ovf" } // Errors templates := map[string]*string{ "guest_additions_sha256": &b.config.GuestAdditionsSHA256, "guest_os_type": &b.config.GuestOSType, "hard_drive_interface": &b.config.HardDriveInterface, "http_directory": &b.config.HTTPDir, "iso_checksum": &b.config.ISOChecksum, "iso_checksum_type": &b.config.ISOChecksumType, "iso_url": &b.config.RawSingleISOUrl, "output_directory": &b.config.OutputDir, "shutdown_command": &b.config.ShutdownCommand, "ssh_key_path": &b.config.SSHKeyPath, "ssh_password": &b.config.SSHPassword, "ssh_username": &b.config.SSHUser, "virtualbox_version_file": &b.config.VBoxVersionFile, "vm_name": &b.config.VMName, "format": &b.config.Format, "boot_wait": &b.config.RawBootWait, "shutdown_timeout": &b.config.RawShutdownTimeout, "ssh_wait_timeout": &b.config.RawSSHWaitTimeout, } for n, ptr := range templates { var err error *ptr, err = b.config.tpl.Process(*ptr, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing %s: %s", n, err)) } } for i, url := range b.config.ISOUrls { var err error b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err)) } } validates := map[string]*string{ "guest_additions_path": &b.config.GuestAdditionsPath, "guest_additions_url": &b.config.GuestAdditionsURL, } for n, ptr := range validates { if err := b.config.tpl.Validate(*ptr); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error parsing %s: %s", n, err)) } } for i, command := range b.config.BootCommand { if err := b.config.tpl.Validate(command); err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing boot_command[%d]: %s", i, err)) } } for i, file := range b.config.FloppyFiles { var err error b.config.FloppyFiles[i], err = b.config.tpl.Process(file, nil) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing floppy_files[%d]: %s", i, err)) } } if !(b.config.Format == "ovf" || b.config.Format == "ova") { errs = packer.MultiErrorAppend( errs, errors.New("invalid format, only 'ovf' or 'ova' are allowed")) } if b.config.HardDriveInterface != "ide" && b.config.HardDriveInterface != "sata" { errs = packer.MultiErrorAppend( errs, errors.New("hard_drive_interface can only be ide or sata")) } if b.config.HTTPPortMin > b.config.HTTPPortMax { errs = packer.MultiErrorAppend( errs, errors.New("http_port_min must be less than http_port_max")) } if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } if b.config.GuestAdditionsSHA256 != "" { b.config.GuestAdditionsSHA256 = strings.ToLower(b.config.GuestAdditionsSHA256) } if !b.config.PackerForce { if _, err := os.Stat(b.config.OutputDir); err == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Output directory '%s' already exists. It must not exist.", b.config.OutputDir)) } } b.config.bootWait, err = time.ParseDuration(b.config.RawBootWait) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing boot_wait: %s", err)) } if b.config.RawShutdownTimeout == "" { b.config.RawShutdownTimeout = "5m" } if b.config.RawSSHWaitTimeout == "" { b.config.RawSSHWaitTimeout = "20m" } b.config.shutdownTimeout, err = time.ParseDuration(b.config.RawShutdownTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err)) } if b.config.SSHKeyPath != "" { if _, err := os.Stat(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } else if _, err := sshKeyToKeyring(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } } if b.config.SSHHostPortMin > b.config.SSHHostPortMax { errs = packer.MultiErrorAppend( errs, errors.New("ssh_host_port_min must be less than ssh_host_port_max")) } if b.config.SSHUser == "" { errs = packer.MultiErrorAppend( errs, errors.New("An ssh_username must be specified.")) } b.config.sshWaitTimeout, err = time.ParseDuration(b.config.RawSSHWaitTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing ssh_wait_timeout: %s", err)) } for i, args := range b.config.VBoxManage { for j, arg := range args { if err := b.config.tpl.Validate(arg); err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing vboxmanage[%d][%d]: %s", i, j, err)) } } } if errs != nil && len(errs.Errors) > 0 { return errs } return nil }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "boot_command", "guest_additions_path", "guest_additions_url", "vboxmanage", "vboxmanage_post", }, }, }, raws...) if err != nil { return nil, err } // Accumulate any errors and warnings var errs *packer.MultiError errs = packer.MultiErrorAppend(errs, b.config.ExportConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.ExportOpts.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend( errs, b.config.OutputConfig.Prepare(&b.config.ctx, &b.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.VBoxManageConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.VBoxManagePostConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.VBoxVersionConfig.Prepare(&b.config.ctx)...) warnings := make([]string, 0) if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } if b.config.GuestAdditionsMode == "" { b.config.GuestAdditionsMode = "upload" } if b.config.GuestAdditionsPath == "" { b.config.GuestAdditionsPath = "VBoxGuestAdditions.iso" } if b.config.HardDriveInterface == "" { b.config.HardDriveInterface = "ide" } if b.config.GuestOSType == "" { b.config.GuestOSType = "Other" } if b.config.ISOInterface == "" { b.config.ISOInterface = "ide" } if b.config.VMName == "" { b.config.VMName = fmt.Sprintf( "packer-%s-%d", b.config.PackerBuildName, interpolate.InitTime.Unix()) } if b.config.HardDriveInterface != "ide" && b.config.HardDriveInterface != "sata" && b.config.HardDriveInterface != "scsi" { errs = packer.MultiErrorAppend( errs, errors.New("hard_drive_interface can only be ide, sata, or scsi")) } if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if b.config.ISOChecksumType != "none" { if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } } if b.config.ISOInterface != "ide" && b.config.ISOInterface != "sata" { errs = packer.MultiErrorAppend( errs, errors.New("iso_interface can only be ide or sata")) } if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } validMode := false validModes := []string{ vboxcommon.GuestAdditionsModeDisable, vboxcommon.GuestAdditionsModeAttach, vboxcommon.GuestAdditionsModeUpload, } for _, mode := range validModes { if b.config.GuestAdditionsMode == mode { validMode = true break } } if !validMode { errs = packer.MultiErrorAppend(errs, fmt.Errorf("guest_additions_mode is invalid. Must be one of: %v", validModes)) } if b.config.GuestAdditionsSHA256 != "" { b.config.GuestAdditionsSHA256 = strings.ToLower(b.config.GuestAdditionsSHA256) } // Warnings if b.config.ISOChecksumType == "none" { warnings = append(warnings, "A checksum type of 'none' was specified. Since ISO files are so big,\n"+ "a checksum is highly recommended.") } if b.config.ShutdownCommand == "" { warnings = append(warnings, "A shutdown_command was not specified. Without a shutdown command, Packer\n"+ "will forcibly halt the virtual machine, which may result in data loss.") } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { md, err := common.DecodeConfig(&b.config, raws...) if err != nil { return nil, err } b.config.tpl, err = packer.NewConfigTemplate() if err != nil { return nil, err } b.config.tpl.UserVars = b.config.PackerUserVars driver, err := hypervcommon.NewHypervPS4Driver() if err != nil { return nil, fmt.Errorf("Failed creating Hyper-V driver: %s", err) } // Accumulate any errors and warnings errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend(errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...) warnings := make([]string, 0) //DiskName if b.config.DiskName == "" { b.config.DiskName = "disk" } //DiskSize err = b.checkDiskSize() if err != nil { errs = packer.MultiErrorAppend(errs, err) } //DiskType if b.config.DiskType == "" { // Default is dynamic b.config.DiskType = DiskTypeDynamic } if b.config.DiskType != DiskTypeDynamic || b.config.DiskType != DiskTypeFixed { errs = packer.MultiErrorAppend(errs, fmt.Errorf("disk_type: %s, invalid disk type, must be %s or %s", b.config.DiskType, DiskTypeDynamic, DiskTypeFixed)) } log.Println(fmt.Sprintf("%s: %s", "DiskType", b.config.DiskType)) //RamSizeMB err = b.checkRamSize() if err != nil { errs = packer.MultiErrorAppend(errs, err) } //FloppyFiles if b.config.FloppyFiles == nil { b.config.FloppyFiles = make([]string, 0) } for i, file := range b.config.FloppyFiles { var err error b.config.FloppyFiles[i], err = b.config.tpl.Process(file, nil) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("Error processing floppy_files[%d]: %s", i, err)) } } //ISOChecksum ISOChecksumType if b.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType) if b.config.ISOChecksumType != "none" { if b.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to large file sizes, an iso_checksum is required")) } else { b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum) } if h := common.HashForType(b.config.ISOChecksumType); h == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType)) } } } //ISOUrls for i, url := range b.config.ISOUrls { var err error b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err)) } } //Version if b.config.Version == "" { b.config.Version = "1" } //VMName if b.config.VMName == "" { b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) } //SkipCompaction if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } //SwitchName if b.config.SwitchName == "" { // no switch name, try to get one attached to a online network adapter onlineSwitchName, err := getExternalOnlineVirtualSwitch(driver) if onlineSwitchName == "" || err != nil { b.config.SwitchName = fmt.Sprintf("pis_%s", uuid.New()) } else { b.config.SwitchName = onlineSwitchName } } // Errors templates := map[string]*string{ "disk_name": &b.config.DiskName, "iso_checksum": &b.config.ISOChecksum, "iso_checksum_type": &b.config.ISOChecksumType, "iso_url": &b.config.RawSingleISOUrl, "vm_name": &b.config.VMName, } for n, ptr := range templates { var err error *ptr, err = b.config.tpl.Process(*ptr, nil) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Error processing %s: %s", n, err)) } } //RawSingleISOUrl if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } else if b.config.RawSingleISOUrl != "" { b.config.ISOUrls = []string{b.config.RawSingleISOUrl} } for i, url := range b.config.ISOUrls { b.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err)) } } // Warnings warning := b.checkHostAvailableMemory(driver) if warning != "" { warnings = appendWarnings(warnings, warning) } if b.config.ISOChecksumType == "none" { warnings = append(warnings, "A checksum type of 'none' was specified. Since ISO files are so big,\n"+ "a checksum is highly recommended.") } if errs != nil && len(errs.Errors) > 0 { return warnings, errs } return warnings, nil }