Add FreeBSD support.
This commit is contained in:
parent
a28edbaa0b
commit
364c415294
|
@ -391,8 +391,11 @@ func checkHyperVGeneration(s string) interface{} {
|
|||
}
|
||||
|
||||
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
|
||||
if runtime.GOOS != "linux" {
|
||||
return nil, errors.New("the azure-chroot builder only works on Linux environments")
|
||||
switch runtime.GOOS {
|
||||
case "linux", "freebsd":
|
||||
break
|
||||
default:
|
||||
return nil, errors.New("the azure-chroot builder only works on Linux and FreeBSD environments")
|
||||
}
|
||||
|
||||
err := b.config.ClientConfig.FillParameters()
|
||||
|
|
|
@ -3,24 +3,18 @@ package chroot
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
|
||||
"github.com/Azure/go-autorest/autorest/azure"
|
||||
"github.com/Azure/go-autorest/autorest/to"
|
||||
"github.com/hashicorp/packer/builder/azure/common/client"
|
||||
)
|
||||
|
||||
type DiskAttacher interface {
|
||||
AttachDisk(ctx context.Context, disk string) (lun int32, err error)
|
||||
DiskPathForLun(lun int32) string
|
||||
WaitForDevice(ctx context.Context, i int32) (device string, err error)
|
||||
DetachDisk(ctx context.Context, disk string) (err error)
|
||||
WaitForDetach(ctx context.Context, diskID string) error
|
||||
|
@ -38,79 +32,6 @@ type diskAttacher struct {
|
|||
vm *client.ComputeInfo // store info about this VM so that we don't have to ask metadata service on every call
|
||||
}
|
||||
|
||||
func (diskAttacher) DiskPathForLun(lun int32) string {
|
||||
return fmt.Sprintf("/dev/disk/azure/scsi1/lun%d", lun)
|
||||
}
|
||||
|
||||
func (da diskAttacher) WaitForDevice(ctx context.Context, lun int32) (device string, err error) {
|
||||
path := da.DiskPathForLun(lun)
|
||||
|
||||
for {
|
||||
link, err := os.Readlink(path)
|
||||
if err == nil {
|
||||
return filepath.Abs("/dev/disk/azure/scsi1/" + link)
|
||||
} else if err != os.ErrNotExist {
|
||||
if pe, ok := err.(*os.PathError); ok && pe.Err != syscall.ENOENT {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
// continue
|
||||
case <-ctx.Done():
|
||||
return "", ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (da *diskAttacher) DetachDisk(ctx context.Context, diskID string) error {
|
||||
log.Println("Fetching list of disks currently attached to VM")
|
||||
currentDisks, err := da.getDisks(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("Removing %q from list of disks currently attached to VM", diskID)
|
||||
newDisks := []compute.DataDisk{}
|
||||
for _, disk := range currentDisks {
|
||||
if disk.ManagedDisk != nil &&
|
||||
!strings.EqualFold(to.String(disk.ManagedDisk.ID), diskID) {
|
||||
newDisks = append(newDisks, disk)
|
||||
}
|
||||
}
|
||||
if len(currentDisks) == len(newDisks) {
|
||||
return DiskNotFoundError
|
||||
}
|
||||
|
||||
log.Println("Updating new list of disks attached to VM")
|
||||
err = da.setDisks(ctx, newDisks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (da *diskAttacher) WaitForDetach(ctx context.Context, diskID string) error {
|
||||
for { // loop until disk is not attached, timeout or error
|
||||
list, err := da.getDisks(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if findDiskInList(list, diskID) == nil {
|
||||
log.Println("Disk is no longer in VM model, assuming detached")
|
||||
return nil
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(time.Second): //continue
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var DiskNotFoundError = errors.New("Disk not found")
|
||||
|
||||
func (da *diskAttacher) AttachDisk(ctx context.Context, diskID string) (int32, error) {
|
||||
|
@ -160,6 +81,53 @@ findFreeLun:
|
|||
return lun, nil
|
||||
}
|
||||
|
||||
func (da *diskAttacher) DetachDisk(ctx context.Context, diskID string) error {
|
||||
log.Println("Fetching list of disks currently attached to VM")
|
||||
currentDisks, err := da.getDisks(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("Removing %q from list of disks currently attached to VM", diskID)
|
||||
newDisks := []compute.DataDisk{}
|
||||
for _, disk := range currentDisks {
|
||||
if disk.ManagedDisk != nil &&
|
||||
!strings.EqualFold(to.String(disk.ManagedDisk.ID), diskID) {
|
||||
newDisks = append(newDisks, disk)
|
||||
}
|
||||
}
|
||||
if len(currentDisks) == len(newDisks) {
|
||||
return DiskNotFoundError
|
||||
}
|
||||
|
||||
log.Println("Updating new list of disks attached to VM")
|
||||
err = da.setDisks(ctx, newDisks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (da *diskAttacher) WaitForDetach(ctx context.Context, diskID string) error {
|
||||
for { // loop until disk is not attached, timeout or error
|
||||
list, err := da.getDisks(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if findDiskInList(list, diskID) == nil {
|
||||
log.Println("Disk is no longer in VM model, assuming detached")
|
||||
return nil
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(time.Second): //continue
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (da *diskAttacher) getThisVM(ctx context.Context) (compute.VirtualMachine, error) {
|
||||
// getting resource info for this VM
|
||||
if da.vm == nil {
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (da diskAttacher) WaitForDevice(ctx context.Context, lun int32) (device string, err error) {
|
||||
// This builder will always be running in Azure, where data disks show up
|
||||
// on scbus5 target 0. The camcontrol command always outputs LUNs in
|
||||
// unpadded hexadecimal format.
|
||||
regexStr := fmt.Sprintf(`at scbus5 target 0 lun %x \(.*?da([\d]+)`, lun)
|
||||
devRegex, err := regexp.Compile(regexStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for {
|
||||
cmd := exec.Command("camcontrol", "devlist")
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
outString := out.String()
|
||||
scanner := bufio.NewScanner(strings.NewReader(outString))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
// Check if this is the correct bus, target, and LUN.
|
||||
if matches := devRegex.FindStringSubmatch(line); matches != nil {
|
||||
// If this function immediately returns, devfs won't have
|
||||
// created the device yet.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
return fmt.Sprintf("/dev/da%s", matches[1]), nil
|
||||
}
|
||||
}
|
||||
if err = scanner.Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
// continue
|
||||
case <-ctx.Done():
|
||||
return "", ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package chroot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func diskPathForLun(lun int32) string {
|
||||
return fmt.Sprintf("/dev/disk/azure/scsi1/lun%d", lun)
|
||||
}
|
||||
|
||||
func (da diskAttacher) WaitForDevice(ctx context.Context, lun int32) (device string, err error) {
|
||||
path := diskPathForLun(lun)
|
||||
|
||||
for {
|
||||
link, err := os.Readlink(path)
|
||||
if err == nil {
|
||||
return filepath.Abs("/dev/disk/azure/scsi1/" + link)
|
||||
} else if err != os.ErrNotExist {
|
||||
if pe, ok := err.(*os.PathError); ok && pe.Err != syscall.ENOENT {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
// continue
|
||||
case <-ctx.Done():
|
||||
return "", ctx.Err()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
|
@ -62,7 +63,13 @@ func (s *StepMountDevice) Run(ctx context.Context, state multistep.StateBag) mul
|
|||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
deviceMount := fmt.Sprintf("%s%s", device, s.MountPartition)
|
||||
var deviceMount string
|
||||
switch runtime.GOOS {
|
||||
case "freebsd":
|
||||
deviceMount = fmt.Sprintf("%sp%s", device, s.MountPartition)
|
||||
default:
|
||||
deviceMount = fmt.Sprintf("%s%s", device, s.MountPartition)
|
||||
}
|
||||
|
||||
state.Put("deviceMount", deviceMount)
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
|
@ -31,12 +32,22 @@ func (s *StepCopyFiles) Run(ctx context.Context, state multistep.StateBag) multi
|
|||
s.files = make([]string, 0, len(s.Files))
|
||||
if len(s.Files) > 0 {
|
||||
ui.Say("Copying files from host to chroot...")
|
||||
var removeDestinationOption string
|
||||
switch runtime.GOOS {
|
||||
case "freebsd":
|
||||
// The -f option here is closer to GNU --remove-destination than
|
||||
// what POSIX says -f should do.
|
||||
removeDestinationOption = "-f"
|
||||
default:
|
||||
// This is the GNU binutils version.
|
||||
removeDestinationOption = "--remove-destination"
|
||||
}
|
||||
for _, path := range s.Files {
|
||||
ui.Message(path)
|
||||
chrootPath := filepath.Join(mountPath, path)
|
||||
log.Printf("Copying '%s' to '%s'", path, chrootPath)
|
||||
|
||||
cmdText, err := wrappedCommand(fmt.Sprintf("cp --remove-destination %s %s", path, chrootPath))
|
||||
cmdText, err := wrappedCommand(fmt.Sprintf("cp %s %s %s", removeDestinationOption, path, chrootPath))
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error building copy command: %s", err)
|
||||
state.Put("error", err)
|
||||
|
|
Loading…
Reference in New Issue