macOS support (#54)

This commit is contained in:
Michael Kuzmin 2018-03-05 01:59:59 +03:00 committed by GitHub
commit 92689b6ee8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 269 additions and 19 deletions

View File

@ -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 {
@ -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
@ -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
}
@ -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
driver/vm_cdrom.go Normal file
View File

@ -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
}

View File

@ -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
examples/macos/setup/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
out/

View File

@ -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

View File

@ -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

View File

@ -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
examples/macos/setup/setup.sh Executable file
View File

@ -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"

View File

@ -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" {

View File

@ -22,6 +22,7 @@ type Config struct {
CreateConfig `mapstructure:",squash"`
CDRomConfig `mapstructure:",squash"`
FloppyConfig `mapstructure:",squash"`
ConfigParamsConfig `mapstructure:",squash"`
ctx interpolate.Context
}

View File

@ -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))

36
iso/step_config_params.go Normal file
View File

@ -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) {}

View File

@ -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 {
@ -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 {