Skip to content

Commit

Permalink
Merge pull request coreos#1241 from sohankunkerkar/azure-gen2-test
Browse files Browse the repository at this point in the history
Add support for Azure gen2 VMs
  • Loading branch information
sohankunkerkar authored Jul 28, 2021
2 parents 4ba8be2 + 1cff42c commit 25d6d05
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 41 deletions.
2 changes: 0 additions & 2 deletions internal/distro/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
// -X github.com/coreos/ignition/v2/internal/distro.mdadmCmd=/opt/bin/mdadm
var (
// Device node directories and paths
diskByIDDir = "/dev/disk/by-id"
diskByLabelDir = "/dev/disk/by-label"
diskByPartUUIDDir = "/dev/disk/by-partuuid"

Expand Down Expand Up @@ -80,7 +79,6 @@ var (
resultFilePath = "/var/lib/ignition/result.json"
)

func DiskByIDDir() string { return diskByIDDir }
func DiskByLabelDir() string { return diskByLabelDir }
func DiskByPartUUIDDir() string { return diskByPartUUIDDir }

Expand Down
41 changes: 41 additions & 0 deletions internal/exec/util/blkid.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
static inline void _free_probe(blkid_probe *pr) { if (pr) blkid_free_probe(*pr); }
#define _cleanup_probe_ __attribute__((cleanup(_free_probe)))

static inline void _free_cache(blkid_cache *gcache) { blkid_put_cache(*gcache); }
#define _cleanup_cache_ __attribute__((cleanup(_free_cache)))

static inline void _free_iterator(blkid_dev_iterate *iter) { blkid_dev_iterate_end(*iter); }
#define _cleanup_iterator_ __attribute__((cleanup(_free_iterator)))

static result_t extract_part_info(blkid_partition part, struct partition_info *info, long sector_divisor);

static result_t checked_copy(char *dest, const char *src, size_t len);
Expand Down Expand Up @@ -248,3 +254,38 @@ static result_t extract_part_info(blkid_partition part, struct partition_info *i

return RESULT_OK;
}

// blkid_get_block_devices fetches block devices with the given FSTYPE
result_t blkid_get_block_devices(const char *fstype, struct block_device_list *device) {
blkid_dev_iterate iter _cleanup_iterator_ = NULL;
blkid_dev dev;
blkid_cache cache _cleanup_cache_ = NULL;
int err, count = 0;
const char *ctmp;

if (blkid_get_cache(&cache, "/dev/null") != 0)
return RESULT_GET_CACHE_FAILED;

if (blkid_probe_all(cache) != 0)
return RESULT_PROBE_FAILED;

iter = blkid_dev_iterate_begin(cache);

blkid_dev_set_search(iter, "TYPE", fstype);

while (blkid_dev_next(iter, &dev) == 0) {
dev = blkid_verify(cache, dev);
if (!dev)
continue;
if (count >= MAX_BLOCK_DEVICES)
return RESULT_MAX_BLOCK_DEVICES;
ctmp = blkid_dev_devname(dev);
err = checked_copy(device->path[count], ctmp, MAX_BLOCK_DEVICE_PATH_LEN);
if (err)
return err;
count++;
}

device->count = count;
return RESULT_OK;
}
21 changes: 21 additions & 0 deletions internal/exec/util/blkid.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ func cResultToErr(res C.result_t) error {
return errors.New("bad partition index specified")
case C.RESULT_GET_PARTLIST_FAILED:
return errors.New("failed to get list of partitions")
case C.RESULT_GET_CACHE_FAILED:
return fmt.Errorf("failed to retrieve cache")
case C.RESULT_DISK_HAS_NO_TYPE:
return errors.New("disk has no type string, despite having a partition table")
case C.RESULT_DISK_NOT_GPT:
Expand All @@ -118,6 +120,8 @@ func cResultToErr(res C.result_t) error {
return errors.New("bad parameters passed")
case C.RESULT_OVERFLOW:
return errors.New("return value doesn't fit in buffer")
case C.RESULT_MAX_BLOCK_DEVICES:
return fmt.Errorf("found too many filesystems of the specified type")
case C.RESULT_NO_TOPO:
return errors.New("failed to get topology information")
case C.RESULT_NO_SECTOR_SIZE:
Expand Down Expand Up @@ -190,3 +194,20 @@ func filesystemLookup(device string, allowAmbivalent bool, fieldName string) (st
}
return string(buf[:bytes.IndexByte(buf[:], 0)]), nil
}

// GetBlockDevices returns a slice of block devices with the given filesystem
func GetBlockDevices(fstype string) ([]string, error) {
var dev C.struct_block_device_list
res := C.blkid_get_block_devices(C.CString(fstype), &dev)

if res != C.RESULT_OK {
return nil, cResultToErr(res)
}

length := int(dev.count)
blkDeviceList := make([]string, length)
for i := 0; i < length; i++ {
blkDeviceList[i] = C.GoString(&dev.path[i][0])
}
return blkDeviceList, nil
}
13 changes: 12 additions & 1 deletion internal/exec/util/blkid.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ typedef enum {
RESULT_NO_PARTITION_TABLE,
RESULT_BAD_INDEX,
RESULT_GET_PARTLIST_FAILED,
RESULT_GET_CACHE_FAILED,
RESULT_DISK_HAS_NO_TYPE,
RESULT_DISK_NOT_GPT,
RESULT_BAD_PARAMS,
RESULT_OVERFLOW,
RESULT_MAX_BLOCK_DEVICES,
RESULT_NO_TOPO,
RESULT_NO_SECTOR_SIZE,
RESULT_BAD_SECTOR_SIZE,
Expand All @@ -48,6 +50,14 @@ struct partition_info {
int number;
};

#define MAX_BLOCK_DEVICES 10
#define MAX_BLOCK_DEVICE_PATH_LEN 50

struct block_device_list {
char path[MAX_BLOCK_DEVICES][MAX_BLOCK_DEVICE_PATH_LEN];
int count;
};

result_t blkid_lookup(const char *device, bool allow_ambivalent, const char *field_name, char buf[], size_t buf_len);

result_t blkid_get_num_partitions(const char *device, int *ret);
Expand All @@ -57,5 +67,6 @@ result_t blkid_get_logical_sector_size(const char *device, int *ret_sector_size)
// WARNING part_num may not be what you expect. see the .c file's comment for why
result_t blkid_get_partition(const char *device, int part_num, struct partition_info *info);

#endif // _BLKID_H_
result_t blkid_get_block_devices(const char *fstype, struct block_device_list *device);

#endif // _BLKID_H_
83 changes: 45 additions & 38 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)

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
checkedDevices := make(map[string]struct{})
for {
for _, ovfFsType := range ovfFsTypes {
devices, 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 _, dev := range devices {
_, checked := checkedDevices[dev]
// verify that this is a CD-ROM drive. This helps
// to avoid reading data from an arbitrary block
// device attached to the VM by the user.
if !checked && isCdromPresent(logger, dev) {
rawConfig, err := getRawConfig(f, dev, ovfFsType)
if err != nil {
logger.Debug("failed to retrieve config from device %q: %v", dev, err)
} else {
return util.ParseConfig(logger, rawConfig)
}
}
checkedDevices[dev] = struct{}{}
}
}
// wait for the actual config drive to appear
// if it's not shown up yet
time.Sleep(time.Second)
}
}

// 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 from device %q: %v", devicePath, 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 25d6d05

Please sign in to comment.