<commit_before>package iso

import (
	"bufio"
	"bytes"
	"encoding/csv"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"path/filepath"
	"strings"
	"time"

	vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
	commonssh "github.com/hashicorp/packer/common/ssh"
	"github.com/hashicorp/packer/communicator/ssh"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
	gossh "golang.org/x/crypto/ssh"
)

// ESX5 driver talks to an ESXi5 hypervisor remotely over SSH to build
// virtual machines. This driver can only manage one machine at a time.
type ESX5Driver struct {
	base vmwcommon.VmwareDriver

	Host           string
	Port           uint
	Username       string
	Password       string
	PrivateKey     string
	Datastore      string
	CacheDatastore string
	CacheDirectory string

	comm      packer.Communicator
	outputDir string
	vmId      string
}

func (d *ESX5Driver) Clone(dst, src string) error {
	return errors.New("Cloning is not supported with the ESX driver.")
}

func (d *ESX5Driver) CompactDisk(diskPathLocal string) error {
	return nil
}

func (d *ESX5Driver) CreateDisk(diskPathLocal string, size string, adapter_type string, typeId string) error {
	diskPath := d.datastorePath(diskPathLocal)
	return d.sh("vmkfstools", "-c", size, "-d", typeId, "-a", adapter_type, diskPath)
}

func (d *ESX5Driver) IsRunning(string) (bool, error) {
	state, err := d.run(nil, "vim-cmd", "vmsvc/power.getstate", d.vmId)
	if err != nil {
		return false, err
	}
	return strings.Contains(state, "Powered on"), nil
}

func (d *ESX5Driver) ReloadVM() error {
	return d.sh("vim-cmd", "vmsvc/reload", d.vmId)
}

func (d *ESX5Driver) Start(vmxPathLocal string, headless bool) error {
	for i := 0; i < 20; i++ {
		//intentionally not checking for error since poweron may fail specially after initial VM registration
		d.sh("vim-cmd", "vmsvc/power.on", d.vmId)
		time.Sleep((time.Duration(i) * time.Second) + 1)
		running, err := d.IsRunning(vmxPathLocal)
		if err != nil {
			return err
		}
		if running {
			return nil
		}
	}
	return errors.New("Retry limit exceeded")
}

func (d *ESX5Driver) Stop(vmxPathLocal string) error {
	return d.sh("vim-cmd", "vmsvc/power.off", d.vmId)
}

func (d *ESX5Driver) Register(vmxPathLocal string) error {
	vmxPath := filepath.ToSlash(filepath.Join(d.outputDir, filepath.Base(vmxPathLocal)))
	if err := d.upload(vmxPath, vmxPathLocal); err != nil {
		return err
	}
	r, err := d.run(nil, "vim-cmd", "solo/registervm", vmxPath)
	if err != nil {
		return err
	}
	d.vmId = strings.TrimRight(r, "\n")
	return nil
}

func (d *ESX5Driver) SuppressMessages(vmxPath string) error {
	return nil
}

func (d *ESX5Driver) Unregister(vmxPathLocal string) error {
	return d.sh("vim-cmd", "vmsvc/unregister", d.vmId)
}

func (d *ESX5Driver) Destroy() error {
	return d.sh("vim-cmd", "vmsvc/destroy", d.vmId)
}

func (d *ESX5Driver) IsDestroyed() (bool, error) {
	err := d.sh("test", "!", "-e", d.outputDir)
	if err != nil {
		return false, err
	}
	return true, err
}

func (d *ESX5Driver) UploadISO(localPath string, checksum string, checksumType string) (string, error) {
	finalPath := d.cachePath(localPath)
	if err := d.mkdir(filepath.ToSlash(filepath.Dir(finalPath))); err != nil {
		return "", err
	}

	log.Printf("Verifying checksum of %s", finalPath)
	if d.verifyChecksum(checksumType, checksum, finalPath) {
		log.Println("Initial checksum matched, no upload needed.")
		return finalPath, nil
	}

	if err := d.upload(finalPath, localPath); err != nil {
		return "", err
	}

	return finalPath, nil
}

func (d *ESX5Driver) RemoveCache(localPath string) error {
	finalPath := d.cachePath(localPath)
	log.Printf("Removing remote cache path %s (local %s)", finalPath, localPath)
	return d.sh("rm", "-rf", finalPath)
}

func (d *ESX5Driver) ToolsIsoPath(string) string {
	return ""
}

func (d *ESX5Driver) ToolsInstall() error {
	return d.sh("vim-cmd", "vmsvc/tools.install", d.vmId)
}

func (d *ESX5Driver) Verify() error {
	// Ensure that NetworkMapper is nil, since the mapping of device<->network
	// is handled by ESX and thus can't be performed by packer unless we
	// query things.

	// FIXME: If we want to expose the network devices to the user, then we can<commit_msg>we never expect remote cache to be a directory.<commit_after>package iso

import (
	"bufio"
	"bytes"
	"encoding/csv"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"path/filepath"
	"strings"
	"time"

	vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
	commonssh "github.com/hashicorp/packer/common/ssh"
	"github.com/hashicorp/packer/communicator/ssh"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
	gossh "golang.org/x/crypto/ssh"
)

// ESX5 driver talks to an ESXi5 hypervisor remotely over SSH to build
// virtual machines. This driver can only manage one machine at a time.
type ESX5Driver struct {
	base vmwcommon.VmwareDriver

	Host           string
	Port           uint
	Username       string
	Password       string
	PrivateKey     string
	Datastore      string
	CacheDatastore string
	CacheDirectory string

	comm      packer.Communicator
	outputDir string
	vmId      string
}

func (d *ESX5Driver) Clone(dst, src string) error {
	return errors.New("Cloning is not supported with the ESX driver.")
}

func (d *ESX5Driver) CompactDisk(diskPathLocal string) error {
	return nil
}

func (d *ESX5Driver) CreateDisk(diskPathLocal string, size string, adapter_type string, typeId string) error {
	diskPath := d.datastorePath(diskPathLocal)
	return d.sh("vmkfstools", "-c", size, "-d", typeId, "-a", adapter_type, diskPath)
}

func (d *ESX5Driver) IsRunning(string) (bool, error) {
	state, err := d.run(nil, "vim-cmd", "vmsvc/power.getstate", d.vmId)
	if err != nil {
		return false, err
	}
	return strings.Contains(state, "Powered on"), nil
}

func (d *ESX5Driver) ReloadVM() error {
	return d.sh("vim-cmd", "vmsvc/reload", d.vmId)
}

func (d *ESX5Driver) Start(vmxPathLocal string, headless bool) error {
	for i := 0; i < 20; i++ {
		//intentionally not checking for error since poweron may fail specially after initial VM registration
		d.sh("vim-cmd", "vmsvc/power.on", d.vmId)
		time.Sleep((time.Duration(i) * time.Second) + 1)
		running, err := d.IsRunning(vmxPathLocal)
		if err != nil {
			return err
		}
		if running {
			return nil
		}
	}
	return errors.New("Retry limit exceeded")
}

func (d *ESX5Driver) Stop(vmxPathLocal string) error {
	return d.sh("vim-cmd", "vmsvc/power.off", d.vmId)
}

func (d *ESX5Driver) Register(vmxPathLocal string) error {
	vmxPath := filepath.ToSlash(filepath.Join(d.outputDir, filepath.Base(vmxPathLocal)))
	if err := d.upload(vmxPath, vmxPathLocal); err != nil {
		return err
	}
	r, err := d.run(nil, "vim-cmd", "solo/registervm", vmxPath)
	if err != nil {
		return err
	}
	d.vmId = strings.TrimRight(r, "\n")
	return nil
}

func (d *ESX5Driver) SuppressMessages(vmxPath string) error {
	return nil
}

func (d *ESX5Driver) Unregister(vmxPathLocal string) error {
	return d.sh("vim-cmd", "vmsvc/unregister", d.vmId)
}

func (d *ESX5Driver) Destroy() error {
	return d.sh("vim-cmd", "vmsvc/destroy", d.vmId)
}

func (d *ESX5Driver) IsDestroyed() (bool, error) {
	err := d.sh("test", "!", "-e", d.outputDir)
	if err != nil {
		return false, err
	}
	return true, err
}

func (d *ESX5Driver) UploadISO(localPath string, checksum string, checksumType string) (string, error) {
	finalPath := d.cachePath(localPath)
	if err := d.mkdir(filepath.ToSlash(filepath.Dir(finalPath))); err != nil {
		return "", err
	}

	log.Printf("Verifying checksum of %s", finalPath)
	if d.verifyChecksum(checksumType, checksum, finalPath) {
		log.Println("Initial checksum matched, no upload needed.")
		return finalPath, nil
	}

	if err := d.upload(finalPath, localPath); err != nil {
		return "", err
	}

	return finalPath, nil
}

func (d *ESX5Driver) RemoveCache(localPath string) error {
	finalPath := d.cachePath(localPath)
	log.Printf("Removing remote cache path %s (local %s)", finalPath, localPath)
	return d.sh("rm", "-f", finalPath)
}

func (d *ESX5Driver) ToolsIsoPath(string) string {
	return ""
}

func (d *ESX5Driver) ToolsInstall() error {
	return d.sh("vim-cmd", "vmsvc/tools.install", d.vmId)
}

func (d *ESX5Driver) Verify() error {
	// Ensure that NetworkMapper is nil, since the mapping of device<->network
	// is handled by ESX and thus can't be performed by packer unless we
	// query things.

	// FIXME: If we want to expose the network devices to the user, then we can
{'fraction_non_alphanumeric': 0.134803632503833, 'fraction_numerical': 0.005661044934544168, 'mean_word_length': 4.102286401925391, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7638459', 'n_tokens_mistral': 3209, 'n_tokens_neox': 3112, 'n_words': 853}