diff --git a/builder/vmware/common/driver_mock.go b/builder/vmware/common/driver_mock.go new file mode 100644 index 000000000..8e73990fa --- /dev/null +++ b/builder/vmware/common/driver_mock.go @@ -0,0 +1,113 @@ +package common + +import ( + "github.com/mitchellh/multistep" +) + +type DriverMock struct { + CompactDiskCalled bool + CompactDiskPath string + CompactDiskErr error + + CreateDiskCalled bool + CreateDiskOutput string + CreateDiskSize string + CreateDiskTypeId string + CreateDiskErr error + + IsRunningCalled bool + IsRunningPath string + IsRunningResult bool + IsRunningErr error + + SSHAddressCalled bool + SSHAddressState multistep.StateBag + SSHAddressResult string + SSHAddressErr error + + StartCalled bool + StartPath string + StartHeadless bool + StartErr error + + StopCalled bool + StopPath string + StopErr error + + SuppressMessagesCalled bool + SuppressMessagesPath string + SuppressMessagesErr error + + ToolsIsoPathCalled bool + ToolsIsoPathFlavor string + ToolsIsoPathResult string + + DhcpLeasesPathCalled bool + DhcpLeasesPathDevice string + DhcpLeasesPathResult string + + VerifyCalled bool + VerifyErr error +} + +func (d *DriverMock) CompactDisk(path string) error { + d.CompactDiskCalled = true + d.CompactDiskPath = path + return d.CompactDiskErr +} + +func (d *DriverMock) CreateDisk(output string, size string, typeId string) error { + d.CreateDiskCalled = true + d.CreateDiskOutput = output + d.CreateDiskSize = size + d.CreateDiskTypeId = typeId + return d.CreateDiskErr +} + +func (d *DriverMock) IsRunning(path string) (bool, error) { + d.IsRunningCalled = true + d.IsRunningPath = path + return d.IsRunningResult, d.IsRunningErr +} + +func (d *DriverMock) SSHAddress(state multistep.StateBag) (string, error) { + d.SSHAddressCalled = true + d.SSHAddressState = state + return d.SSHAddressResult, d.SSHAddressErr +} + +func (d *DriverMock) Start(path string, headless bool) error { + d.StartCalled = true + d.StartPath = path + d.StartHeadless = headless + return d.StartErr +} + +func (d *DriverMock) Stop(path string) error { + d.StopCalled = true + d.StopPath = path + return d.StopErr +} + +func (d *DriverMock) SuppressMessages(path string) error { + d.SuppressMessagesCalled = true + d.SuppressMessagesPath = path + return d.SuppressMessagesErr +} + +func (d *DriverMock) ToolsIsoPath(flavor string) string { + d.ToolsIsoPathCalled = true + d.ToolsIsoPathFlavor = flavor + return d.ToolsIsoPathResult +} + +func (d *DriverMock) DhcpLeasesPath(device string) string { + d.DhcpLeasesPathCalled = true + d.DhcpLeasesPathDevice = device + return d.DhcpLeasesPathResult +} + +func (d *DriverMock) Verify() error { + d.VerifyCalled = true + return d.VerifyErr +} diff --git a/builder/vmware/common/driver_mock_test.go b/builder/vmware/common/driver_mock_test.go new file mode 100644 index 000000000..5a056e149 --- /dev/null +++ b/builder/vmware/common/driver_mock_test.go @@ -0,0 +1,9 @@ +package common + +import ( + "testing" +) + +func TestDriverMock_impl(t *testing.T) { + var _ Driver = new(DriverMock) +} diff --git a/builder/vmware/common/guest_ip_test.go b/builder/vmware/common/guest_ip_test.go new file mode 100644 index 000000000..fdd6b4c9c --- /dev/null +++ b/builder/vmware/common/guest_ip_test.go @@ -0,0 +1,82 @@ +package common + +import ( + "io/ioutil" + "os" + "testing" +) + +func TestDHCPLeaseGuestLookup_impl(t *testing.T) { + var _ GuestIPFinder = new(DHCPLeaseGuestLookup) +} + +func TestDHCPLeaseGuestLookup(t *testing.T) { + tf, err := ioutil.TempFile("", "packer") + if err != nil { + t.Fatalf("err: %s", err) + } + if _, err := tf.Write([]byte(testLeaseContents)); err != nil { + t.Fatalf("err: %s", err) + } + tf.Close() + defer os.Remove(tf.Name()) + + driver := new(DriverMock) + driver.DhcpLeasesPathResult = tf.Name() + + finder := &DHCPLeaseGuestLookup{ + Driver: driver, + Device: "vmnet8", + MACAddress: "00:0c:29:59:91:02", + } + + ip, err := finder.GuestIP() + if err != nil { + t.Fatalf("err: %s", err) + } + + if !driver.DhcpLeasesPathCalled { + t.Fatal("should ask for DHCP leases path") + } + if driver.DhcpLeasesPathDevice != "vmnet8" { + t.Fatal("should be vmnet8") + } + + if ip != "192.168.126.130" { + t.Fatalf("bad: %#v", ip) + } +} + +const testLeaseContents = ` +# All times in this file are in UTC (GMT), not your local timezone. This is +# not a bug, so please don't ask about it. There is no portable way to +# store leases in the local timezone, so please don't request this as a +# feature. If this is inconvenient or confusing to you, we sincerely +# apologize. Seriously, though - don't ask. +# The format of this file is documented in the dhcpd.leases(5) manual page. + +lease 192.168.126.129 { + starts 0 2013/09/15 23:58:51; + ends 1 2013/09/16 00:28:51; + hardware ethernet 00:0c:29:59:91:02; + client-hostname "precise64"; +} +lease 192.168.126.130 { + starts 2 2013/09/17 21:39:07; + ends 2 2013/09/17 22:09:07; + hardware ethernet 00:0c:29:59:91:02; + client-hostname "precise64"; +} +lease 192.168.126.128 { + starts 0 2013/09/15 20:09:59; + ends 0 2013/09/15 20:21:58; + hardware ethernet 00:0c:29:59:91:02; + client-hostname "precise64"; +} +lease 192.168.126.127 { + starts 0 2013/09/15 20:09:59; + ends 0 2013/09/15 20:21:58; + hardware ethernet 01:0c:29:59:91:02; + client-hostname "precise64"; + +` diff --git a/builder/vmware/iso/guest_ip.go b/builder/vmware/iso/guest_ip.go deleted file mode 100644 index 9d9713096..000000000 --- a/builder/vmware/iso/guest_ip.go +++ /dev/null @@ -1,91 +0,0 @@ -package iso - -import ( - "errors" - "io/ioutil" - "log" - "os" - "regexp" - "strings" - "time" - - vmwcommon "github.com/mitchellh/packer/builder/vmware/common" -) - -// Interface to help find the IP address of a running virtual machine. -type GuestIPFinder interface { - GuestIP() (string, error) -} - -// DHCPLeaseGuestLookup looks up the IP address of a guest using DHCP -// lease information from the VMware network devices. -type DHCPLeaseGuestLookup struct { - // Driver that is being used (to find leases path) - Driver vmwcommon.Driver - - // Device that the guest is connected to. - Device string - - // MAC address of the guest. - MACAddress string -} - -func (f *DHCPLeaseGuestLookup) GuestIP() (string, error) { - dhcpLeasesPath := f.Driver.DhcpLeasesPath(f.Device) - log.Printf("DHCP leases path: %s", dhcpLeasesPath) - if dhcpLeasesPath == "" { - return "", errors.New("no DHCP leases path found.") - } - - fh, err := os.Open(dhcpLeasesPath) - if err != nil { - return "", err - } - defer fh.Close() - - dhcpBytes, err := ioutil.ReadAll(fh) - if err != nil { - return "", err - } - - var lastIp string - var lastLeaseEnd time.Time - - var curIp string - var curLeaseEnd time.Time - - ipLineRe := regexp.MustCompile(`^lease (.+?) {$`) - endTimeLineRe := regexp.MustCompile(`^\s*ends \d (.+?);$`) - macLineRe := regexp.MustCompile(`^\s*hardware ethernet (.+?);$`) - - for _, line := range strings.Split(string(dhcpBytes), "\n") { - // Need to trim off CR character when running in windows - line = strings.TrimRight(line, "\r") - - matches := ipLineRe.FindStringSubmatch(line) - if matches != nil { - lastIp = matches[1] - continue - } - - matches = endTimeLineRe.FindStringSubmatch(line) - if matches != nil { - lastLeaseEnd, _ = time.Parse("2006/01/02 15:04:05", matches[1]) - continue - } - - // If the mac address matches and this lease ends farther in the - // future than the last match we might have, then choose it. - matches = macLineRe.FindStringSubmatch(line) - if matches != nil && matches[1] == f.MACAddress && curLeaseEnd.Before(lastLeaseEnd) { - curIp = lastIp - curLeaseEnd = lastLeaseEnd - } - } - - if curIp == "" { - return "", errors.New("IP not found for MAC in DHCP leases") - } - - return curIp, nil -}