Пример #1
0
func (s *StepRun) Run(state multistep.StateBag) multistep.StepAction {
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)
	vmName := state.Get("vmName").(string)

	ui.Say("Starting the virtual machine...")

	err := driver.Start(vmName)
	if err != nil {
		err := fmt.Errorf("Error starting vm: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	s.vmName = vmName

	if int64(s.BootWait) > 0 {
		ui.Say(fmt.Sprintf("Waiting %s for boot...", s.BootWait))
		wait := time.After(s.BootWait)
	WAITLOOP:
		for {
			select {
			case <-wait:
				break WAITLOOP
			case <-time.After(1 * time.Second):
				if _, ok := state.GetOk(multistep.StateCancelled); ok {
					return multistep.ActionHalt
				}
			}
		}
	}

	return multistep.ActionContinue
}
Пример #2
0
func (s *StepAttachFloppy) Run(state multistep.StateBag) multistep.StepAction {
	// Determine if we even have a floppy disk to attach
	var floppyPath string
	if floppyPathRaw, ok := state.GetOk("floppy_path"); ok {
		floppyPath = floppyPathRaw.(string)
	} else {
		log.Println("No floppy disk, not attaching.")
		return multistep.ActionContinue
	}

	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)
	vmName := state.Get("vmName").(string)

	ui.Say("Attaching floppy disk...")

	// Create the floppy disk controller
	command := []string{
		"set", vmName,
		"--device-add", "fdd",
		"--image", floppyPath,
	}
	if err := driver.Prlctl(command...); err != nil {
		state.Put("error", fmt.Errorf("Error adding floppy: %s", err))
		return multistep.ActionHalt
	}

	// Track the path so that we can unregister it from Parallels later
	s.floppyPath = floppyPath

	return multistep.ActionContinue
}
Пример #3
0
func (s *StepOutputDir) Cleanup(state multistep.StateBag) {
	if !s.cleanup {
		return
	}

	_, cancelled := state.GetOk(multistep.StateCancelled)
	_, halted := state.GetOk(multistep.StateHalted)

	if cancelled || halted {
		ui := state.Get("ui").(packer.Ui)

		ui.Say("Deleting output directory...")
		/*
			for i := 0; i < 5; i++ {
				err := os.RemoveAll(s.Path)
				if err == nil {
					break
				}

				log.Printf("Error removing output dir: %s", err)
				time.Sleep(2 * time.Second)
			}
		*/
	}
}
Пример #4
0
func (s *StepOutputDir) Cleanup(state multistep.StateBag) {
	if !s.success {
		return
	}

	_, cancelled := state.GetOk(multistep.StateCancelled)
	_, halted := state.GetOk(multistep.StateHalted)

	if cancelled || halted {
		/*
			dir := state.Get("dir").(OutputDir)
			ui := state.Get("ui").(packer.Ui)

			exists, _ := dir.DirExists()
			if exists {
				ui.Say("Deleting output directory...")
				for i := 0; i < 5; i++ {
					err := dir.RemoveAll()
					if err == nil {
						break
					}

					log.Printf("Error removing output dir: %s", err)
					time.Sleep(2 * time.Second)
				}
			}
		*/
	}
}
Пример #5
0
func cancelCallback(state multistep.StateBag) bool {
	cancel := false
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		cancel = true
	}
	return cancel
}
func (s *StepCreateSourceMachine) Cleanup(state multistep.StateBag) {
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)

	machineIdRaw, ok := state.GetOk("machine")
	if ok && machineIdRaw.(string) != "" {
		machineId := machineIdRaw.(string)
		ui.Say(fmt.Sprintf("Stopping source machine (%s)...", machineId))
		err := driver.StopMachine(machineId)
		if err != nil {
			state.Put("error", fmt.Errorf("Problem stopping source machine: %s", err))
			return
		}

		ui.Say(fmt.Sprintf("Waiting for source machine to stop (%s)...", machineId))
		err = driver.WaitForMachineState(machineId, "stopped", 10*time.Minute)
		if err != nil {
			state.Put("error", fmt.Errorf("Problem waiting for source machine to stop: %s", err))
			return
		}

		ui.Say(fmt.Sprintf("Deleting source machine (%s)...", machineId))
		err = driver.DeleteMachine(machineId)
		if err != nil {
			state.Put("error", fmt.Errorf("Problem deleting source machine: %s", err))
			return
		}
	}
}
Пример #7
0
func (s *stepCreateVM) Cleanup(state multistep.StateBag) {
	if s.vmName == "" {
		return
	}

	driver := state.Get("driver").(vboxcommon.Driver)
	ui := state.Get("ui").(packer.Ui)
	config := state.Get("config").(*Config)

	_, cancelled := state.GetOk(multistep.StateCancelled)
	_, halted := state.GetOk(multistep.StateHalted)
	if (config.KeepRegistered) && (!cancelled && !halted) {
		ui.Say("Keeping virtual machine registered with VirtualBox host (keep_registered = true)")
		return
	}

	ui.Say("Unregistering and deleting virtual machine...")
	var err error = nil
	for i := 0; i < 5; i++ {
		err = driver.VBoxManage("unregistervm", s.vmName, "--delete")
		if err == nil {
			break
		}

		time.Sleep(1 * time.Second * time.Duration(i))
	}

	if err != nil {
		ui.Error(fmt.Sprintf("Error deleting virtual machine: %s", err))
	}
}
Пример #8
0
func (s *stepCreateVersion) Cleanup(state multistep.StateBag) {
	client := state.Get("client").(*VagrantCloudClient)
	ui := state.Get("ui").(packer.Ui)
	box := state.Get("box").(*Box)
	version := state.Get("version").(*Version)

	_, cancelled := state.GetOk(multistep.StateCancelled)
	_, halted := state.GetOk(multistep.StateHalted)

	// Return if we didn't cancel or halt, and thus need
	// no cleanup
	if !cancelled && !halted {
		return
	}

	path := fmt.Sprintf("box/%s/version/%v", box.Tag, version.Version)

	ui.Say("Cleaning up version")
	ui.Message(fmt.Sprintf("Deleting version: %s", version.Version))

	// No need for resp from the cleanup DELETE
	_, err := client.Delete(path)

	if err != nil {
		ui.Error(fmt.Sprintf("Error destroying version: %s", err))
	}

}
Пример #9
0
func (s *stepCreateVersion) Cleanup(state multistep.StateBag) {
	client := state.Get("client").(*VagrantCloudClient)
	ui := state.Get("ui").(packer.Ui)
	config := state.Get("config").(Config)
	box := state.Get("box").(*Box)

	// If we didn't save the version number, it likely doesn't exist or
	// already existed
	if s.number == 0 {
		ui.Message("Version was not created or previously existed, not deleting")
		return
	}

	_, cancelled := state.GetOk(multistep.StateCancelled)
	_, halted := state.GetOk(multistep.StateHalted)

	// Return if we didn't cancel or halt, and thus need
	// no cleanup
	if !cancelled && !halted {
		return
	}

	path := fmt.Sprintf("box/%s/version/%v", box.Tag, s.number)

	ui.Say("Cleaning up version")
	ui.Message(fmt.Sprintf("Deleting version: %s", config.Version))

	// No need for resp from the cleanup DELETE
	_, err := client.Delete(path)

	if err != nil {
		ui.Error(fmt.Sprintf("Error destroying version: %s", err))
	}

}
Пример #10
0
func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) {
	config := state.Get("config").(*Config)
	var privateKey string

	var auth []gossh.AuthMethod

	if config.Comm.SSHPassword != "" {
		auth = []gossh.AuthMethod{
			gossh.Password(config.Comm.SSHPassword),
			gossh.KeyboardInteractive(
				ssh.PasswordKeyboardInteractive(config.Comm.SSHPassword)),
		}
	}

	if config.Comm.SSHPrivateKey != "" {
		if priv, ok := state.GetOk("privateKey"); ok {
			privateKey = priv.(string)
		}
		signer, err := gossh.ParsePrivateKey([]byte(privateKey))
		if err != nil {
			return nil, fmt.Errorf("Error setting up SSH config: %s", err)
		}
		if err != nil {
			return nil, err
		}

		auth = append(auth, gossh.PublicKeys(signer))
	}
	return &gossh.ClientConfig{
		User: config.Comm.SSHUsername,
		Auth: auth,
	}, nil
}
Пример #11
0
func (s *StepProvision) Run(state multistep.StateBag) multistep.StepAction {
	comm := s.Comm
	if comm == nil {
		comm = state.Get("communicator").(packer.Communicator)
	}

	hook := state.Get("hook").(packer.Hook)
	ui := state.Get("ui").(packer.Ui)

	// Run the provisioner in a goroutine so we can continually check
	// for cancellations...
	log.Println("Running the provision hook")
	errCh := make(chan error, 1)
	go func() {
		errCh <- hook.Run(packer.HookProvision, ui, comm, nil)
	}()

	for {
		select {
		case err := <-errCh:
			if err != nil {
				state.Put("error", err)
				return multistep.ActionHalt
			}

			return multistep.ActionContinue
		case <-time.After(1 * time.Second):
			if _, ok := state.GetOk(multistep.StateCancelled); ok {
				log.Println("Cancelling provisioning due to interrupt...")
				hook.Cancel()
				return multistep.ActionHalt
			}
		}
	}
}
Пример #12
0
func (s *stepCreateProvider) Cleanup(state multistep.StateBag) {
	client := state.Get("client").(*VagrantCloudClient)
	ui := state.Get("ui").(packer.Ui)
	box := state.Get("box").(*Box)
	version := state.Get("version").(*Version)

	// If we didn't save the provider name, it likely doesn't exist
	if s.name == "" {
		ui.Say("Cleaning up provider")
		ui.Message("Provider was not created, not deleting")
		return
	}

	_, cancelled := state.GetOk(multistep.StateCancelled)
	_, halted := state.GetOk(multistep.StateHalted)

	// Return if we didn't cancel or halt, and thus need
	// no cleanup
	if !cancelled && !halted {
		return
	}

	ui.Say("Cleaning up provider")
	ui.Message(fmt.Sprintf("Deleting provider: %s", s.name))

	path := fmt.Sprintf("box/%s/version/%v/provider/%s", box.Tag, version.Number, s.name)

	// No need for resp from the cleanup DELETE
	_, err := client.Delete(path)

	if err != nil {
		ui.Error(fmt.Sprintf("Error destroying provider: %s", err))
	}
}
Пример #13
0
func (s *stepUpdateState) Cleanup(state multistep.StateBag) {
	buildJob := state.Get("buildJob").(Job)
	ctx := state.Get("ctx").(gocontext.Context)

	mresult, ok := state.GetOk("scriptResult")

	if ok {
		result := mresult.(*backend.RunResult)

		var err error

		switch result.ExitCode {
		case 0:
			err = buildJob.Finish(FinishStatePassed)
		case 1:
			err = buildJob.Finish(FinishStateFailed)
		default:
			err = buildJob.Finish(FinishStateErrored)
		}

		if err != nil {
			context.LoggerFromContext(ctx).WithField("err", err).Error("couldn't mark job as finished")
		}
	}
}
Пример #14
0
// Cleanup destroys the GCE instance created during the image creation process.
func (s *StepCreateInstance) Cleanup(state multistep.StateBag) {
	nameRaw, ok := state.GetOk("instance_name")
	if !ok {
		return
	}
	name := nameRaw.(string)
	if name == "" {
		return
	}

	config := state.Get("config").(*Config)
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)

	ui.Say("Deleting instance...")
	errCh, err := driver.DeleteInstance(config.Zone, name)
	if err == nil {
		select {
		case err = <-errCh:
		case <-time.After(config.stateTimeout):
			err = errors.New("time out while waiting for instance to delete")
		}
	}

	if err != nil {
		ui.Error(fmt.Sprintf(
			"Error deleting instance. Please delete it manually.\n\n"+
				"Name: %s\n"+
				"Error: %s", name, err))
	}

	state.Put("instance_name", "")
	return
}
Пример #15
0
func (s *stepCreateServer) Cleanup(state multistep.StateBag) {
	c := state.Get("config").(*Config)
	ui := state.Get("ui").(packer.Ui)

	ui.Say("Removing Server...")

	token := oneandone.SetToken(c.Token)
	//Create an API client
	api := oneandone.New(token, oneandone.BaseUrl)

	var serverId string
	if temp, ok := state.GetOk("server_id"); ok {
		serverId = temp.(string)
	}

	if serverId != "" {
		server, err := api.ShutdownServer(serverId, false)
		if err != nil {
			ui.Error(fmt.Sprintf("Error shutting down 1and1 server. Please destroy it manually: %s", serverId))
			ui.Error(err.Error())
		}
		err = api.WaitForState(server, "POWERED_OFF", 10, c.Retries)

		server, err = api.DeleteServer(server.Id, false)

		if err != nil {
			ui.Error(fmt.Sprintf("Error deleting 1and1 server. Please destroy it manually: %s", serverId))
			ui.Error(err.Error())
		}
	}
}
Пример #16
0
func (s *StepMountFloppydrive) Run(state multistep.StateBag) multistep.StepAction {
	// Determine if we even have a floppy disk to attach
	var floppyPath string
	if floppyPathRaw, ok := state.GetOk("floppy_path"); ok {
		floppyPath = floppyPathRaw.(string)
	} else {
		log.Println("No floppy disk, not attaching.")
		return multistep.ActionContinue
	}

	// Hyper-V is really dumb and can't figure out the format of the file
	// without an extension, so we need to add the "vfd" extension to the
	// floppy.
	floppyPath, err := s.copyFloppy(floppyPath)
	if err != nil {
		state.Put("error", fmt.Errorf("Error preparing floppy: %s", err))
		return multistep.ActionHalt
	}

	ui := state.Get("ui").(packer.Ui)
	ui.Say("Mounting floppy drive...")
	vmName := state.Get("vmName").(string)
	driver := state.Get("driver").(hypervcommon.Driver)

	err = mountFloppyDrive(driver, vmName, floppyPath)
	if err != nil {
		state.Put("error", fmt.Errorf("Error mounting floppy drive: %s", err))
		return multistep.ActionHalt
	}

	// Track the path so that we can unregister it from Hyper-V later
	s.floppyPath = floppyPath

	return multistep.ActionContinue
}
Пример #17
0
func (s *stepWaitForShutdown) Run(state multistep.StateBag) multistep.StepAction {
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)

	stopCh := make(chan struct{})
	defer close(stopCh)

	cancelCh := make(chan struct{})
	go func() {
		for {
			if _, ok := state.GetOk(multistep.StateCancelled); ok {
				close(cancelCh)
				return
			}

			select {
			case <-stopCh:
				return
			case <-time.After(100 * time.Millisecond):
			}
		}
	}()

	ui.Say(s.Message)
	driver.WaitForShutdown(cancelCh)
	return multistep.ActionContinue
}
Пример #18
0
func (s *stepRun) Run(state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(*config)
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)
	vmxPath := state.Get("vmx_path").(string)
	vncIp := state.Get("vnc_ip").(string)
	vncPort := state.Get("vnc_port").(uint)

	// Set the VMX path so that we know we started the machine
	s.bootTime = time.Now()
	s.vmxPath = vmxPath

	ui.Say("Starting virtual machine...")
	if config.Headless {
		ui.Message(fmt.Sprintf(
			"The VM will be run headless, without a GUI. If you want to\n"+
				"view the screen of the VM, connect via VNC without a password to\n"+
				"%s:%d", vncIp, vncPort))
	}

	if remoteDriver, ok := driver.(RemoteDriver); ok {
		if err := remoteDriver.Register(vmxPath); err != nil {
			err := fmt.Errorf("Error registering VM: %s", err)
			state.Put("error", err)
			ui.Error(err.Error())
			return multistep.ActionHalt
		}

		s.registered = true
	}

	if err := driver.Start(vmxPath, config.Headless); err != nil {
		err := fmt.Errorf("Error starting VM: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	// Wait the wait amount
	if int64(config.bootWait) > 0 {
		ui.Say(fmt.Sprintf("Waiting %s for boot...", config.bootWait.String()))
		wait := time.After(config.bootWait)
	WAITLOOP:
		for {
			select {
			case <-wait:
				break WAITLOOP
			case <-time.After(1 * time.Second):
				if _, ok := state.GetOk(multistep.StateCancelled); ok {
					return multistep.ActionHalt
				}
			}
		}

	}

	return multistep.ActionContinue
}
Пример #19
0
func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(*config)
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)
	vmName := state.Get("vmName").(string)

	// Clear out the Packer-created forwarding rule
	ui.Say("Preparing to export machine...")
	ui.Message(fmt.Sprintf("Deleting forwarded port mapping for SSH (host port %d)", state.Get("sshHostPort")))
	command := []string{"modifyvm", vmName, "--natpf1", "delete", "packerssh"}
	if err := driver.VBoxManage(command...); err != nil {
		err := fmt.Errorf("Error deleting port forwarding rule: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	// Remove the attached floppy disk, if it exists
	if _, ok := state.GetOk("floppy_path"); ok {
		ui.Message("Removing floppy drive...")
		command := []string{
			"storageattach", vmName,
			"--storagectl", "Floppy Controller",
			"--port", "0",
			"--device", "0",
			"--medium", "none",
		}
		if err := driver.VBoxManage(command...); err != nil {
			state.Put("error", fmt.Errorf("Error removing floppy: %s", err))
			return multistep.ActionHalt
		}

	}

	// Export the VM to an OVF
	outputPath := filepath.Join(config.OutputDir, vmName+"."+config.Format)

	command = []string{
		"export",
		vmName,
		"--output",
		outputPath,
	}

	ui.Say("Exporting virtual machine...")
	err := driver.VBoxManage(command...)
	if err != nil {
		err := fmt.Errorf("Error exporting virtual machine: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	state.Put("exportPath", outputPath)

	return multistep.ActionContinue
}
Пример #20
0
func (s *StepGetPassword) Run(state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(Config)
	ui := state.Get("ui").(packer.Ui)

	// Skip if we're not using winrm
	if s.Comm.Type != "winrm" {
		log.Printf("[INFO] Not using winrm communicator, skipping get password...")
		return multistep.ActionContinue
	}

	// If we already have a password, skip it
	if s.Comm.WinRMPassword != "" {
		ui.Say("Skipping waiting for password since WinRM password set...")
		return multistep.ActionContinue
	}

	// We need the v2 compute client
	computeClient, err := config.computeV2Client()
	if err != nil {
		err = fmt.Errorf("Error initializing compute client: %s", err)
		state.Put("error", err)
		return multistep.ActionHalt
	}

	ui.Say("Waiting for password since WinRM password is not set...")
	server := state.Get("server").(*servers.Server)
	var password string

	privateKey, err := ssh.ParseRawPrivateKey([]byte(state.Get("privateKey").(string)))
	if err != nil {
		err = fmt.Errorf("Error parsing private key: %s", err)
		state.Put("error", err)
		return multistep.ActionHalt
	}

	for ; password == "" && err == nil; password, err = servers.GetPassword(computeClient, server.ID).ExtractPassword(privateKey.(*rsa.PrivateKey)) {

		// Check for an interrupt in between attempts.
		if _, ok := state.GetOk(multistep.StateCancelled); ok {
			return multistep.ActionHalt
		}

		log.Printf("Retrying to get a administrator password evry 5 seconds.")
		time.Sleep(5 * time.Second)
	}

	ui.Message(fmt.Sprintf("Password retrieved!"))
	s.Comm.WinRMPassword = password

	// In debug-mode, we output the password
	if s.Debug {
		ui.Message(fmt.Sprintf(
			"Password (since debug is enabled) \"%s\"", s.Comm.WinRMPassword))
	}

	return multistep.ActionContinue
}
Пример #21
0
// Cleanup destroys the GCE instance created during the image creation process.
func (s *StepCreateInstance) Cleanup(state multistep.StateBag) {
	nameRaw, ok := state.GetOk("instance_name")
	if !ok {
		return
	}
	name := nameRaw.(string)
	if name == "" {
		return
	}

	config := state.Get("config").(*Config)
	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)

	ui.Say("Deleting instance...")
	errCh, err := driver.DeleteInstance(config.Zone, name)
	if err == nil {
		select {
		case err = <-errCh:
		case <-time.After(config.stateTimeout):
			err = errors.New("time out while waiting for instance to delete")
		}
	}

	if err != nil {
		ui.Error(fmt.Sprintf(
			"Error deleting instance. Please delete it manually.\n\n"+
				"Name: %s\n"+
				"Error: %s", name, err))
	}

	ui.Message("Instance has been deleted!")
	state.Put("instance_name", "")

	// Deleting the instance does not remove the boot disk. This cleanup removes
	// the disk.
	ui.Say("Deleting disk...")
	errCh, err = driver.DeleteDisk(config.Zone, config.DiskName)
	if err == nil {
		select {
		case err = <-errCh:
		case <-time.After(config.stateTimeout):
			err = errors.New("time out while waiting for disk to delete")
		}
	}

	if err != nil {
		ui.Error(fmt.Sprintf(
			"Error deleting disk. Please delete it manually.\n\n"+
				"Name: %s\n"+
				"Error: %s", config.InstanceName, err))
	}

	ui.Message("Disk has been deleted!")

	return
}
Пример #22
0
func (s *stepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(*config)
	driver := state.Get("driver").(vboxcommon.Driver)
	httpPort := state.Get("http_port").(uint)
	ui := state.Get("ui").(packer.Ui)
	vmName := state.Get("vmName").(string)

	tplData := &bootCommandTemplateData{
		"10.0.2.2",
		httpPort,
		config.VMName,
	}

	ui.Say("Typing the boot command...")
	for _, command := range config.BootCommand {
		command, err := config.tpl.Process(command, tplData)
		if err != nil {
			err := fmt.Errorf("Error preparing boot command: %s", err)
			state.Put("error", err)
			ui.Error(err.Error())
			return multistep.ActionHalt
		}

		for _, code := range scancodes(command) {
			if code == "wait" {
				time.Sleep(1 * time.Second)
				continue
			}

			if code == "wait5" {
				time.Sleep(5 * time.Second)
				continue
			}

			if code == "wait10" {
				time.Sleep(10 * time.Second)
				continue
			}

			// Since typing is sometimes so slow, we check for an interrupt
			// in between each character.
			if _, ok := state.GetOk(multistep.StateCancelled); ok {
				return multistep.ActionHalt
			}

			if err := driver.VBoxManage("controlvm", vmName, "keyboardputscancode", code); err != nil {
				err := fmt.Errorf("Error sending boot command: %s", err)
				state.Put("error", err)
				ui.Error(err.Error())
				return multistep.ActionHalt
			}
		}
	}

	return multistep.ActionContinue
}
Пример #23
0
func (s *StepConfigureVMX) Run(state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	vmxPath := state.Get("vmx_path").(string)

	vmxContents, err := ioutil.ReadFile(vmxPath)
	if err != nil {
		err := fmt.Errorf("Error reading VMX file: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	vmxData := ParseVMX(string(vmxContents))

	// Set this so that no dialogs ever appear from Packer.
	vmxData["msg.autoanswer"] = "true"

	// Create a new UUID for this VM, since it is a new VM
	vmxData["uuid.action"] = "create"

	// Delete any generated addresses since we want to regenerate
	// them. Conflicting MAC addresses is a bad time.
	addrRegex := regexp.MustCompile(`(?i)^ethernet\d+\.generatedAddress`)
	for k, _ := range vmxData {
		if addrRegex.MatchString(k) {
			delete(vmxData, k)
		}
	}

	// Set custom data
	for k, v := range s.CustomData {
		log.Printf("Setting VMX: '%s' = '%s'", k, v)
		k = strings.ToLower(k)
		vmxData[k] = v
	}

	// Set a floppy disk, but only if we should
	if !s.SkipFloppy {
		// Set a floppy disk if we have one
		if floppyPathRaw, ok := state.GetOk("floppy_path"); ok {
			log.Println("Floppy path present, setting in VMX")
			vmxData["floppy0.present"] = "TRUE"
			vmxData["floppy0.filetype"] = "file"
			vmxData["floppy0.filename"] = floppyPathRaw.(string)
		}
	}

	if err := WriteVMX(vmxPath, vmxData); err != nil {
		err := fmt.Errorf("Error writing VMX file: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}

	return multistep.ActionContinue
}
func (s *stepTypeBootCommand) Run(state multistep.StateBag) multistep.StepAction {
	config := state.Get("config").(*Config)
	httpPort := state.Get("http_port").(uint)
	ui := state.Get("ui").(packer.Ui)
	vncPort := state.Get("vnc_port").(uint)

	// Connect to VNC
	ui.Say("Connecting to VM via VNC")
	nc, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", vncPort))
	if err != nil {
		err := fmt.Errorf("Error connecting to VNC: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}
	defer nc.Close()

	c, err := vnc.Client(nc, &vnc.ClientConfig{Exclusive: false})
	if err != nil {
		err := fmt.Errorf("Error handshaking with VNC: %s", err)
		state.Put("error", err)
		ui.Error(err.Error())
		return multistep.ActionHalt
	}
	defer c.Close()

	log.Printf("Connected to VNC desktop: %s", c.DesktopName)

	ctx := config.ctx
	ctx.Data = &bootCommandTemplateData{
		"10.0.2.2",
		httpPort,
		config.VMName,
	}

	ui.Say("Typing the boot command over VNC...")
	for _, command := range config.BootCommand {
		command, err := interpolate.Render(command, &ctx)
		if err != nil {
			err := fmt.Errorf("Error preparing boot command: %s", err)
			state.Put("error", err)
			ui.Error(err.Error())
			return multistep.ActionHalt
		}

		// Check for interrupts between typing things so we can cancel
		// since this isn't the fastest thing.
		if _, ok := state.GetOk(multistep.StateCancelled); ok {
			return multistep.ActionHalt
		}

		vncSendString(c, command)
	}

	return multistep.ActionContinue
}
Пример #25
0
func (s *StepAttachFloppy) Run(state multistep.StateBag) multistep.StepAction {
	// Determine if we even have a floppy disk to attach
	var floppyPath string
	if floppyPathRaw, ok := state.GetOk("floppy_path"); ok {
		floppyPath = floppyPathRaw.(string)
	} else {
		log.Println("No floppy disk, not attaching.")
		return multistep.ActionContinue
	}

	// VirtualBox is really dumb and can't figure out the format of the file
	// without an extension, so we need to add the "vfd" extension to the
	// floppy.
	floppyPath, err := s.copyFloppy(floppyPath)
	if err != nil {
		state.Put("error", fmt.Errorf("Error preparing floppy: %s", err))
		return multistep.ActionHalt
	}

	driver := state.Get("driver").(Driver)
	ui := state.Get("ui").(packer.Ui)
	vmName := state.Get("vmName").(string)

	ui.Say("Attaching floppy disk...")

	// Create the floppy disk controller
	command := []string{
		"storagectl", vmName,
		"--name", "Floppy Controller",
		"--add", "floppy",
	}
	if err := driver.VBoxManage(command...); err != nil {
		state.Put("error", fmt.Errorf("Error creating floppy controller: %s", err))
		return multistep.ActionHalt
	}

	// Attach the floppy to the controller
	command = []string{
		"storageattach", vmName,
		"--storagectl", "Floppy Controller",
		"--port", "0",
		"--device", "0",
		"--type", "fdd",
		"--medium", floppyPath,
	}
	if err := driver.VBoxManage(command...); err != nil {
		state.Put("error", fmt.Errorf("Error attaching floppy: %s", err))
		return multistep.ActionHalt
	}

	// Track the path so that we can unregister it from VirtualBox later
	s.floppyPath = floppyPath

	return multistep.ActionContinue
}
Пример #26
0
func (s abortStep) Cleanup(state multistep.StateBag) {
	if _, ok := state.GetOk(multistep.StateCancelled); ok {
		s.ui.Error("Interrupted, aborting...")
		os.Exit(1)
	}
	if _, ok := state.GetOk(multistep.StateHalted); ok {
		s.ui.Error(fmt.Sprintf("Step %q failed, aborting...", typeName(s.step)))
		os.Exit(1)
	}
	s.step.Cleanup(state)
}
Пример #27
0
func (s StepCleanVMX) Run(state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)
	vmxPath := state.Get("vmx_path").(string)

	ui.Say("Cleaning VMX prior to finishing up...")

	vmxData, err := ReadVMX(vmxPath)
	if err != nil {
		state.Put("error", fmt.Errorf("Error reading VMX: %s", err))
		return multistep.ActionHalt
	}

	if _, ok := state.GetOk("floppy_path"); ok {
		// Delete the floppy0 entries so the floppy is no longer mounted
		ui.Message("Unmounting floppy from VMX...")
		for k, _ := range vmxData {
			if strings.HasPrefix(k, "floppy0.") {
				log.Printf("Deleting key: %s", k)
				delete(vmxData, k)
			}
		}
		vmxData["floppy0.present"] = "FALSE"
	}

	if isoPathRaw, ok := state.GetOk("iso_path"); ok {
		isoPath := isoPathRaw.(string)

		ui.Message("Detaching ISO from CD-ROM device...")
		devRe := regexp.MustCompile(`^ide\d:\d\.`)
		for k, _ := range vmxData {
			match := devRe.FindString(k)
			if match == "" {
				continue
			}

			filenameKey := match + "filename"
			if filename, ok := vmxData[filenameKey]; ok {
				if filename == isoPath {
					// Change the CD-ROM device back to auto-detect to eject
					vmxData[filenameKey] = "auto detect"
					vmxData[match+"devicetype"] = "cdrom-raw"
				}
			}
		}
	}

	// Rewrite the VMX
	if err := WriteVMX(vmxPath, vmxData); err != nil {
		state.Put("error", fmt.Errorf("Error writing VMX: %s", err))
		return multistep.ActionHalt
	}

	return multistep.ActionContinue
}
Пример #28
0
func (s *StepConnectSSH) Run(state multistep.StateBag) multistep.StepAction {
	ui := state.Get("ui").(packer.Ui)

	var comm packer.Communicator
	var err error

	cancel := make(chan struct{})
	waitDone := make(chan bool, 1)
	go func() {
		ui.Say("Waiting for SSH to become available...")
		comm, err = s.waitForSSH(state, cancel)
		waitDone <- true
	}()

	log.Printf("[INFO] Waiting for SSH, up to timeout: %s", s.Config.SSHTimeout)
	timeout := time.After(s.Config.SSHTimeout)
WaitLoop:
	for {
		// Wait for either SSH to become available, a timeout to occur,
		// or an interrupt to come through.
		select {
		case <-waitDone:
			if err != nil {
				ui.Error(fmt.Sprintf("Error waiting for SSH: %s", err))
				state.Put("error", err)
				return multistep.ActionHalt
			}

			ui.Say("Connected to SSH!")
			state.Put("communicator", comm)
			break WaitLoop
		case <-timeout:
			err := fmt.Errorf("Timeout waiting for SSH.")
			state.Put("error", err)
			ui.Error(err.Error())
			close(cancel)
			return multistep.ActionHalt
		case <-time.After(1 * time.Second):
			if _, ok := state.GetOk(multistep.StateCancelled); ok {
				// The step sequence was cancelled, so cancel waiting for SSH
				// and just start the halting process.
				close(cancel)
				log.Println("[WARN] Interrupt detected, quitting waiting for SSH.")
				return multistep.ActionHalt
			}
		}
	}

	return multistep.ActionContinue
}
// steps should check config.ShouldKeepVM first before cleaning up the VM
func (c CommonConfig) ShouldKeepVM(state multistep.StateBag) bool {
	switch c.KeepVM {
	case "always":
		return true
	case "never":
		return false
	case "on_success":
		// only keep instance if build was successful
		_, cancelled := state.GetOk(multistep.StateCancelled)
		_, halted := state.GetOk(multistep.StateHalted)
		return !(cancelled || halted)
	default:
		panic(fmt.Sprintf("Unknown keep_vm value '%s'", c.KeepVM))
	}
}
/* Wait waits for up to Timeout duration, checking an optional Predicate every PredicateInterval duration.
   The first run of Predicate is immediately after Wait is called.
   If the command is interrupted by the user, then an InterruptedError is returned.
   If Predicate is not nil, a timeout leads to TimeoutError being returned, and a successful Predicate run leads to nil being returned.
   If Predicate is nil, a timeout is not an error, and nil is returned.
*/
func (wait InterruptibleWait) Wait(state multistep.StateBag) error {
	predicateResult := make(chan PredicateResult, 1)
	stopWaiting := make(chan struct{})
	defer close(stopWaiting)

	if wait.Predicate != nil {
		go func() {
			for {
				if complete, err := wait.Predicate(); err != nil || complete {
					predicateResult <- PredicateResult{complete, err}
					return
				}

				select {
				case <-time.After(wait.PredicateInterval):
					continue
				case <-stopWaiting:
					return
				}
			}
		}()
	}

	timeout := time.After(wait.Timeout)
	for {
		// wait for either install to complete/error,
		// an interrupt to come through, or a timeout to occur

		if _, ok := state.GetOk(multistep.StateCancelled); ok {
			return InterruptedError{}
		}

		select {
		case result := <-predicateResult:
			return result.err

		case <-time.After(1 * time.Second):
			continue

		case <-timeout:
			if wait.Predicate != nil {
				return TimeoutError{}
			} else {
				return nil
			}
		}
	}
}