Skip to content

Commit

Permalink
Merge pull request #773 from EmilienM/configDrive
Browse files Browse the repository at this point in the history
openstack: dynamically mount the config-drive
  • Loading branch information
zeeke authored Oct 9, 2024
2 parents c02e517 + 084810a commit 92cf81c
Showing 1 changed file with 92 additions and 23 deletions.
115 changes: 92 additions & 23 deletions pkg/platforms/openstack/openstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"

Expand All @@ -21,15 +23,18 @@ import (
)

const (
ospHostMetaDataDir = "/host/var/config/openstack/2018-08-27"
ospMetaDataDir = "/var/config/openstack/2018-08-27"
ospMetaDataBaseURL = "http://169.254.169.254/openstack/2018-08-27"
ospNetworkDataJSON = "network_data.json"
ospMetaDataJSON = "meta_data.json"
ospHostNetworkDataFile = ospHostMetaDataDir + "/" + ospNetworkDataJSON
ospHostMetaDataFile = ospHostMetaDataDir + "/" + ospMetaDataJSON
ospNetworkDataURL = ospMetaDataBaseURL + "/" + ospNetworkDataJSON
ospMetaDataURL = ospMetaDataBaseURL + "/" + ospMetaDataJSON
varConfigPath = "/var/config"
ospMetaDataBaseDir = "/openstack/2018-08-27"
ospMetaDataDir = varConfigPath + ospMetaDataBaseDir
ospMetaDataBaseURL = "http://169.254.169.254" + ospMetaDataBaseDir
ospNetworkDataJSON = "network_data.json"
ospMetaDataJSON = "meta_data.json"
ospNetworkDataURL = ospMetaDataBaseURL + "/" + ospNetworkDataJSON
ospMetaDataURL = ospMetaDataBaseURL + "/" + ospMetaDataJSON
// Config drive is defined as an iso9660 or vfat (deprecated) drive
// with the "config-2" label.
//https://docs.openstack.org/nova/latest/user/config-drive.html
configDriveLabel = "config-2"
)

var (
Expand Down Expand Up @@ -109,9 +114,10 @@ func New(hostManager host.HostManagerInterface) OpenstackInterface {
}

// GetOpenstackData gets the metadata and network_data
func getOpenstackData(useHostPath bool) (metaData *OSPMetaData, networkData *OSPNetworkData, err error) {
metaData, networkData, err = getOpenstackDataFromConfigDrive(useHostPath)
func getOpenstackData(mountConfigDrive bool) (metaData *OSPMetaData, networkData *OSPNetworkData, err error) {
metaData, networkData, err = getOpenstackDataFromConfigDrive(mountConfigDrive)
if err != nil {
log.Log.Error(err, "GetOpenStackData(): non-fatal error getting OpenStack data from config drive")
metaData, networkData, err = getOpenstackDataFromMetadataService()
if err != nil {
return metaData, networkData, fmt.Errorf("GetOpenStackData(): error getting OpenStack data: %w", err)
Expand Down Expand Up @@ -153,46 +159,109 @@ func getOpenstackData(useHostPath bool) (metaData *OSPMetaData, networkData *OSP
return metaData, networkData, err
}

// getConfigDriveDevice returns the config drive device which was found
func getConfigDriveDevice() (string, error) {
dev := "/dev/disk/by-label/" + configDriveLabel
if _, err := os.Stat(dev); os.IsNotExist(err) {
out, err := exec.Command(
"blkid", "-l",
"-t", "LABEL="+configDriveLabel,
"-o", "device",
).CombinedOutput()
if err != nil {
return "", fmt.Errorf("unable to run blkid: %v", err)
}
dev = strings.TrimSpace(string(out))
}
log.Log.Info("found config drive device", "device", dev)
return dev, nil
}

// mountConfigDriveDevice mounts the config drive and return the path
func mountConfigDriveDevice(device string) (string, error) {
if device == "" {
return "", fmt.Errorf("device is empty")
}
tmpDir, err := os.MkdirTemp("", "sriov-configdrive")
if err != nil {
return "", fmt.Errorf("error creating temp directory: %w", err)
}
cmd := exec.Command("mount", "-o", "ro", "-t", "auto", device, tmpDir)
if err := cmd.Run(); err != nil {
return "", fmt.Errorf("error mounting config drive: %w", err)
}
log.Log.V(2).Info("mounted config drive device", "device", device, "path", tmpDir)
return tmpDir, nil
}

// ummountConfigDriveDevice ummounts the config drive device
func ummountConfigDriveDevice(path string) error {
if path == "" {
return fmt.Errorf("path is empty")
}
cmd := exec.Command("umount", path)
if err := cmd.Run(); err != nil {
return fmt.Errorf("error umounting config drive: %w", err)
}
log.Log.V(2).Info("umounted config drive", "path", path)
return nil
}

// getOpenstackDataFromConfigDrive reads the meta_data and network_data files
func getOpenstackDataFromConfigDrive(useHostPath bool) (metaData *OSPMetaData, networkData *OSPNetworkData, err error) {
func getOpenstackDataFromConfigDrive(mountConfigDrive bool) (metaData *OSPMetaData, networkData *OSPNetworkData, err error) {
metaData = &OSPMetaData{}
networkData = &OSPNetworkData{}
var configDrivePath string
log.Log.Info("reading OpenStack meta_data from config-drive")
var metadataf *os.File
ospMetaDataFilePath := ospMetaDataFile
if useHostPath {
ospMetaDataFilePath = ospHostMetaDataFile
if mountConfigDrive {
configDriveDevice, err := getConfigDriveDevice()
if err != nil {
return metaData, networkData, fmt.Errorf("error finding config drive device: %w", err)
}
configDrivePath, err = mountConfigDriveDevice(configDriveDevice)
if err != nil {
return metaData, networkData, fmt.Errorf("error mounting config drive device: %w", err)
}
defer func() {
if e := ummountConfigDriveDevice(configDrivePath); err == nil && e != nil {
err = fmt.Errorf("error umounting config drive device: %w", e)
}
if e := os.Remove(configDrivePath); err == nil && e != nil {
err = fmt.Errorf("error removing temp directory %s: %w", configDrivePath, e)
}
}()
ospMetaDataFilePath = filepath.Join(configDrivePath, ospMetaDataBaseDir, ospMetaDataJSON)
ospNetworkDataFile = filepath.Join(configDrivePath, ospMetaDataBaseDir, ospNetworkDataJSON)
}
metadataf, err = os.Open(ospMetaDataFilePath)
if err != nil {
return metaData, networkData, fmt.Errorf("error opening file %s: %w", ospHostMetaDataFile, err)
return metaData, networkData, fmt.Errorf("error opening file %s: %w", ospMetaDataFilePath, err)
}
defer func() {
if e := metadataf.Close(); err == nil && e != nil {
err = fmt.Errorf("error closing file %s: %w", ospHostMetaDataFile, e)
err = fmt.Errorf("error closing file %s: %w", ospMetaDataFilePath, e)
}
}()
if err = json.NewDecoder(metadataf).Decode(&metaData); err != nil {
return metaData, networkData, fmt.Errorf("error unmarshalling metadata from file %s: %w", ospHostMetaDataFile, err)
return metaData, networkData, fmt.Errorf("error unmarshalling metadata from file %s: %w", ospMetaDataFilePath, err)
}

log.Log.Info("reading OpenStack network_data from config-drive")
var networkDataf *os.File
ospNetworkDataFilePath := ospNetworkDataFile
if useHostPath {
ospNetworkDataFilePath = ospHostNetworkDataFile
}
networkDataf, err = os.Open(ospNetworkDataFilePath)
if err != nil {
return metaData, networkData, fmt.Errorf("error opening file %s: %w", ospHostNetworkDataFile, err)
return metaData, networkData, fmt.Errorf("error opening file %s: %w", ospNetworkDataFilePath, err)
}
defer func() {
if e := networkDataf.Close(); err == nil && e != nil {
err = fmt.Errorf("error closing file %s: %w", ospHostNetworkDataFile, e)
err = fmt.Errorf("error closing file %s: %w", ospNetworkDataFilePath, e)
}
}()
if err = json.NewDecoder(networkDataf).Decode(&networkData); err != nil {
return metaData, networkData, fmt.Errorf("error unmarshalling metadata from file %s: %w", ospHostNetworkDataFile, err)
return metaData, networkData, fmt.Errorf("error unmarshalling metadata from file %s: %w", ospNetworkDataFilePath, err)
}
return metaData, networkData, err
}
Expand Down

0 comments on commit 92cf81c

Please sign in to comment.