Skip to content
This repository has been archived by the owner on Mar 8, 2023. It is now read-only.

Commit

Permalink
macOS support (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkuzmin authored Mar 4, 2018
2 parents 611d513 + 548cc3c commit 92689b6
Show file tree
Hide file tree
Showing 13 changed files with 269 additions and 19 deletions.
53 changes: 42 additions & 11 deletions driver/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,16 @@ type CreateConfig struct {
DiskThinProvisioned bool
DiskControllerType string // example: "scsi", "pvscsi"

Annotation string
Name string
Folder string
Host string
ResourcePool string
Datastore string
GuestOS string // example: otherGuest
Network string // "" for default network
NetworkCard string // example: vmxnet3
Annotation string
Name string
Folder string
Host string
ResourcePool string
Datastore string
GuestOS string // example: otherGuest
Network string // "" for default network
NetworkCard string // example: vmxnet3
USBController bool
}

func (d *Driver) NewVM(ref *types.ManagedObjectReference) *VirtualMachine {
Expand Down Expand Up @@ -108,6 +109,14 @@ func (d *Driver) CreateVM(config *CreateConfig) (*VirtualMachine, error) {
return nil, err
}

if config.USBController {
t := true
usb := &types.VirtualUSBController{
EhciEnabled: &t,
}
devices = append(devices, usb)
}

createSpec.DeviceChange, err = devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
if err != nil {
return nil, err
Expand Down Expand Up @@ -446,12 +455,12 @@ func (vm *VirtualMachine) AddCdrom(isoPath string) error {
if err != nil {
return err
}
ide, err := devices.FindIDEController("")
sata, err := vm.FindSATAController()
if err != nil {
return err
}

cdrom, err := devices.CreateCdrom(ide)
cdrom, err := vm.CreateCdrom(sata)
if err != nil {
return err
}
Expand Down Expand Up @@ -519,3 +528,25 @@ func (vm *VirtualMachine) addDevice(device types.BaseVirtualDevice) error {
func convertGiBToKiB(gib int64) int64 {
return gib * 1024 * 1024
}

func (vm *VirtualMachine) AddConfigParams(params map[string]string) error {
var confSpec types.VirtualMachineConfigSpec

var ov []types.BaseOptionValue
for k, v := range params {
o := types.OptionValue{
Key: k,
Value: v,
}
ov = append(ov, &o)
}
confSpec.ExtraConfig = ov

task, err := vm.vm.Reconfigure(vm.driver.ctx, confSpec)
if err != nil {
return err
}

_, err = task.WaitForResult(vm.driver.ctx, nil)
return err
}
48 changes: 48 additions & 0 deletions driver/vm_cdrom.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package driver

import (
"github.com/vmware/govmomi/vim25/types"
"errors"
)

func (vm *VirtualMachine) AddSATAController() error {
sata := &types.VirtualAHCIController{}
return vm.addDevice(sata)
}

func (vm *VirtualMachine) FindSATAController() (*types.VirtualAHCIController, error) {
l, err := vm.Devices()
if err != nil {
return nil, err
}

c := l.PickController((*types.VirtualAHCIController)(nil))
if c == nil {
return nil, errors.New("no available SATA controller")
}

return c.(*types.VirtualAHCIController), nil
}

func (vm *VirtualMachine) CreateCdrom(c *types.VirtualAHCIController) (*types.VirtualCdrom, error) {
l, err := vm.Devices()
if err != nil {
return nil, err
}

device := &types.VirtualCdrom{}

l.AssignController(device, c)

device.Backing = &types.VirtualCdromAtapiBackingInfo{
VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{},
}

device.Connectable = &types.VirtualDeviceConnectInfo{
AllowGuestControl: true,
Connected: true,
StartConnected: true,
}

return device, nil
}
49 changes: 49 additions & 0 deletions examples/macos/macos-10.13.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"builders": [
{
"type": "vsphere-iso",

"vcenter_server": "vcenter.vsphere65.test",
"username": "root",
"password": "jetbrains",
"insecure_connection": "true",

"vm_name": "macos-packer",
"host": "esxi-mac.vsphere65.test",

"guest_os_type": "darwin16_64Guest",

"CPUs": 1,
"RAM": 4096,

"disk_size": 32,
"disk_thin_provisioned": true,

"network_card": "e1000e",
"usb_controller": true,

"configuration_parameters": {
"ich7m.present": "TRUE",
"smc.present": "TRUE"
},

"iso_paths": [
"[datastore-mac] ISO/macOS 10.13.3.iso",
"[datastore-mac] ISO/setup.iso",
"[datastore-mac] ISO/VMware Tools/10.2.0/darwin.iso"
],

"boot_order": "disk,cdrom",

"boot_wait": "4m",
"boot_command": [
"<enter><wait5>",
"<leftCtrlOn><f2><leftCtrlOff>u<enter>t<enter><wait5>",
"/Volumes/setup/setup.sh<enter>"
],

"ssh_username": "jetbrains",
"ssh_password": "jetbrains"
}
]
}
1 change: 1 addition & 0 deletions examples/macos/setup/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
out/
15 changes: 15 additions & 0 deletions examples/macos/setup/iso-macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh
set -eux

# Based on
# https://gist.github.com/agentsim/00cc38c693e7d0e1b36a2080870d955b#gistcomment-2304505

mkdir -p out

hdiutil create -o out/HighSierra.cdr -size 5530m -layout SPUD -fs HFS+J
hdiutil attach out/HighSierra.cdr.dmg -noverify -mountpoint /Volumes/install_build
sudo /Applications/Install\ macOS\ High\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/install_build --nointeraction
hdiutil detach /Volumes/Install\ macOS\ High\ Sierra
hdiutil convert out/HighSierra.cdr.dmg -format UDTO -o out/HighSierra.iso
mv out/HighSierra.iso.cdr out/HighSierra.iso
rm out/HighSierra.cdr.dmg
23 changes: 23 additions & 0 deletions examples/macos/setup/iso-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/sh
set -eux

mkdir -p out/pkgroot
rm -rf /out/pkgroot/*

mkdir -p out/scripts
rm -rf /out/scripts/*
cp postinstall out/scripts/

pkgbuild \
--identifier io.packer.install \
--root out/pkgroot \
--scripts out/scripts \
out/postinstall.pkg

mkdir -p out/iso
rm -rf out/iso/*
cp setup.sh out/iso/
productbuild --package out/postinstall.pkg out/iso/postinstall.pkg

rm out/setup.iso
hdiutil makehybrid -iso -joliet -default-volume-name setup -o out/setup.iso out/iso
24 changes: 24 additions & 0 deletions examples/macos/setup/postinstall
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/sh
set -eu

# Create user account
USERNAME=jetbrains
PASSWORD=jetbrains
dscl . -create "/Users/${USERNAME}"
dscl . -create "/Users/${USERNAME}" UserShell /bin/bash
dscl . -create "/Users/${USERNAME}" RealName "${USERNAME}"
dscl . -create "/Users/${USERNAME}" UniqueID 510
dscl . -create "/Users/${USERNAME}" PrimaryGroupID 20
dscl . -create "/Users/${USERNAME}" NFSHomeDirectory "/Users/${USERNAME}"
dscl . -passwd "/Users/${USERNAME}" "${PASSWORD}"
dscl . -append /Groups/admin GroupMembership "${USERNAME}"
createhomedir -c

# Start VMware Tools daemon explicitly
launchctl load /Library/LaunchDaemons/com.vmware.launchd.tools.plist

# Enable SSH
systemsetup -setremotelogin on

# Disable the welcome screen
touch "$3/private/var/db/.AppleSetupDone"
12 changes: 12 additions & 0 deletions examples/macos/setup/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh

# Format partition
diskutil eraseDisk JHFS+ Disk disk0

# Packages are installed in reversed order - why?
"/Volumes/Image Volume/Install macOS High Sierra.app/Contents/Resources/startosinstall" \
--volume /Volumes/Disk \
--converttoapfs no \
--agreetolicense \
--installpackage "/Volumes/setup/postinstall.pkg" \
--installpackage "/Volumes/VMware Tools/Install VMware Tools.app/Contents/Resources/VMware Tools.pkg"
3 changes: 3 additions & 0 deletions iso/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Config: &b.config.FloppyConfig,
Datastore: b.config.Datastore,
},
&StepConfigParams{
Config: &b.config.ConfigParamsConfig,
},
)

if b.config.Comm.Type != "none" {
Expand Down
1 change: 1 addition & 0 deletions iso/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Config struct {
CreateConfig `mapstructure:",squash"`
CDRomConfig `mapstructure:",squash"`
FloppyConfig `mapstructure:",squash"`
ConfigParamsConfig `mapstructure:",squash"`

ctx interpolate.Context
}
Expand Down
5 changes: 5 additions & 0 deletions iso/step_add_cdrom.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ func (s *StepAddCDRom) Run(state multistep.StateBag) multistep.StepAction {
vm := state.Get("vm").(*driver.VirtualMachine)

ui.Say("Adding CDRoms...")
if err := vm.AddSATAController(); err != nil {
state.Put("error", fmt.Errorf("error adding SATA controller: %v", err))
return multistep.ActionHalt
}

for _, path := range s.Config.ISOPaths {
if err := vm.AddCdrom(path); err != nil {
state.Put("error", fmt.Errorf("error adding a cdrom: %v", err))
Expand Down
36 changes: 36 additions & 0 deletions iso/step_config_params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package iso

import (
"github.com/hashicorp/packer/packer"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
"github.com/mitchellh/multistep"
"fmt"
)

type ConfigParamsConfig struct {
ConfigParams map[string]string `mapstructure:"configuration_parameters"`
}

func (c *ConfigParamsConfig) Prepare() []error {
return nil
}

type StepConfigParams struct {
Config *ConfigParamsConfig
}

func (s *StepConfigParams) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
vm := state.Get("vm").(*driver.VirtualMachine)

ui.Say("Adding configuration parameters...")

if err := vm.AddConfigParams(s.Config.ConfigParams); err != nil {
state.Put("error", fmt.Errorf("error adding configuration parameters: %v", err))
return multistep.ActionHalt
}

return multistep.ActionContinue
}

func (s *StepConfigParams) Cleanup(state multistep.StateBag) {}
18 changes: 10 additions & 8 deletions iso/step_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ type CreateConfig struct {
DiskThinProvisioned bool `mapstructure:"disk_thin_provisioned"`
DiskControllerType string `mapstructure:"disk_controller_type"`

VMName string `mapstructure:"vm_name"`
Folder string `mapstructure:"folder"`
Host string `mapstructure:"host"`
ResourcePool string `mapstructure:"resource_pool"`
Datastore string `mapstructure:"datastore"`
GuestOSType string `mapstructure:"guest_os_type"`
Network string `mapstructure:"network"`
NetworkCard string `mapstructure:"network_card"`
VMName string `mapstructure:"vm_name"`
Folder string `mapstructure:"folder"`
Host string `mapstructure:"host"`
ResourcePool string `mapstructure:"resource_pool"`
Datastore string `mapstructure:"datastore"`
GuestOSType string `mapstructure:"guest_os_type"`
Network string `mapstructure:"network"`
NetworkCard string `mapstructure:"network_card"`
USBController bool `mapstructure:"usb_controller"`
}

func (c *CreateConfig) Prepare() []error {
Expand Down Expand Up @@ -79,6 +80,7 @@ func (s *StepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
GuestOS: s.Config.GuestOSType,
Network: s.Config.Network,
NetworkCard: s.Config.NetworkCard,
USBController: s.Config.USBController,
})

if err != nil {
Expand Down

0 comments on commit 92689b6

Please sign in to comment.