Skip to content

Commit

Permalink
providers/azure: add support for azure gen2 VMs
Browse files Browse the repository at this point in the history
Fixes coreos#1194
This change uses the same devicepath for gen1 and gen2 VMs because
they can't easily be distinguished at runtime.
  • Loading branch information
sohankunkerkar committed Jul 15, 2021
1 parent 342900e commit 815344c
Showing 1 changed file with 44 additions and 37 deletions.
81 changes: 44 additions & 37 deletions internal/providers/azure/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"time"

"github.com/coreos/ignition/v2/config/v3_4_experimental/types"
"github.com/coreos/ignition/v2/internal/distro"
execUtil "github.com/coreos/ignition/v2/internal/exec/util"
"github.com/coreos/ignition/v2/internal/log"
"github.com/coreos/ignition/v2/internal/providers/util"
Expand All @@ -35,8 +34,7 @@ import (
)

const (
configDeviceID = "ata-Virtual_CD"
configPath = "/CustomData.bin"
configPath = "/CustomData.bin"
)

// These constants come from <cdrom.h>.
Expand Down Expand Up @@ -66,29 +64,51 @@ func FetchConfig(f *resource.Fetcher) (types.Config, report.Report, error) {
// FetchFromOvfDevice has the return signature of platform.NewFetcher. It is
// wrapped by this and AzureStack packages.
func FetchFromOvfDevice(f *resource.Fetcher, ovfFsTypes []string) (types.Config, report.Report, error) {
devicePath := filepath.Join(distro.DiskByIDDir(), configDeviceID)

var rawConfig []byte
var err error
logger := f.Logger
logger.Debug("waiting for config DVD...")
waitForCdrom(logger, devicePath)

fsType, err := checkOvfFsType(logger, devicePath, ovfFsTypes)
if err != nil {
return types.Config{}, report.Report{}, err
for _, ovfFsType := range ovfFsTypes {
device, err := execUtil.GetBlockDevices(ovfFsType)
if err != nil {
return types.Config{}, report.Report{}, fmt.Errorf("failed to retrieve block devices with FSTYPE=%q: %v", ovfFsType, err)
}
for len(device) > 0 {
for i, dev := range device {
// verify that this is a CD-ROM device
if isCdromPresent(logger, dev) {
rawConfig, err = getRawConfig(f, dev, ovfFsType)
if len(rawConfig) >= 0 {
return util.ParseConfig(logger, rawConfig)
} else if err != nil && i == len(device) {
logger.Debug("failed to retrieve config: %v", err)
}
}
}
// wait for the actual config drive to appear
// if it's not shown up yet
time.Sleep(time.Second)
device, _ = execUtil.GetBlockDevices(ovfFsType)
}
}
return types.Config{}, report.Report{}, fmt.Errorf("failed to retrieve config: %v", err)
}

// getRawConfig returns the config by mounting the given block device
func getRawConfig(f *resource.Fetcher, devicePath string, fstype string) ([]byte, error) {
logger := f.Logger
mnt, err := ioutil.TempDir("", "ignition-azure")
if err != nil {
return types.Config{}, report.Report{}, fmt.Errorf("failed to create temp directory: %v", err)
return nil, fmt.Errorf("failed to create temp directory: %v", err)
}
defer os.Remove(mnt)

logger.Debug("mounting config device")
if err := logger.LogOp(
func() error { return unix.Mount(devicePath, mnt, fsType, unix.MS_RDONLY, "") },
func() error { return unix.Mount(devicePath, mnt, fstype, unix.MS_RDONLY, "") },
"mounting %q at %q", devicePath, mnt,
); err != nil {
return types.Config{}, report.Report{}, fmt.Errorf("failed to mount device %q at %q: %v", devicePath, mnt, err)
return nil, fmt.Errorf("failed to mount device %q at %q: %v", devicePath, mnt, err)
}
defer func() {
_ = logger.LogOp(
Expand All @@ -97,31 +117,31 @@ func FetchFromOvfDevice(f *resource.Fetcher, ovfFsTypes []string) (types.Config,
)
}()

// detect the config drive by looking for a file which is always present
logger.Debug("checking for config drive")
if _, err := os.Stat(filepath.Join(mnt, "ovf-env.xml")); err != nil {
return nil, fmt.Errorf("device %q does not appear to be a config drive: %v", devicePath, err)
}

logger.Debug("reading config")
rawConfig, err := ioutil.ReadFile(filepath.Join(mnt, configPath))
if err != nil && !os.IsNotExist(err) {
return types.Config{}, report.Report{}, fmt.Errorf("failed to read config: %v", err)
}

return util.ParseConfig(logger, rawConfig)
}

func waitForCdrom(logger *log.Logger, devicePath string) {
for !isCdromPresent(logger, devicePath) {
time.Sleep(time.Second)
return nil, fmt.Errorf("failed to read config: %v", err)
}
return rawConfig, nil
}

// isCdromPresent verifies if the given config drive is CD-ROM
func isCdromPresent(logger *log.Logger, devicePath string) bool {
logger.Debug("opening config device")
logger.Debug("opening config device: %q", devicePath)
device, err := os.Open(devicePath)
if err != nil {
logger.Info("failed to open config device: %v", err)
return false
}
defer device.Close()

logger.Debug("getting drive status")
logger.Debug("getting drive status for %q", devicePath)
status, _, errno := unix.Syscall(
unix.SYS_IOCTL,
uintptr(device.Fd()),
Expand All @@ -146,16 +166,3 @@ func isCdromPresent(logger *log.Logger, devicePath string) bool {

return (status == CDS_DISC_OK)
}

func checkOvfFsType(logger *log.Logger, devicePath string, fsTypes []string) (string, error) {
fs, err := execUtil.GetFilesystemInfo(devicePath, false)
if err != nil {
return fs.Type, fmt.Errorf("failed to detect filesystem on ovf device %q: %v", devicePath, err)
}
for _, f := range fsTypes {
if f == fs.Type {
return fs.Type, nil
}
}
return fs.Type, fmt.Errorf("filesystem %q is not a supported ovf device", fs.Type)
}

0 comments on commit 815344c

Please sign in to comment.