github.com/coreos/mantle@v0.13.0/platform/machine/qemu/flight.go (about)

     1  // Copyright 2016 CoreOS, Inc.
     2  // Copyright 2018 Red Hat
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package qemu
    17  
    18  import (
    19  	"fmt"
    20  	"os"
    21  
    22  	"github.com/coreos/pkg/capnslog"
    23  
    24  	"github.com/coreos/mantle/platform"
    25  	"github.com/coreos/mantle/platform/local"
    26  	"github.com/coreos/mantle/util"
    27  )
    28  
    29  const (
    30  	Platform platform.Name = "qemu"
    31  )
    32  
    33  // Options contains QEMU-specific options for the flight.
    34  type Options struct {
    35  	// DiskImage is the full path to the disk image to boot in QEMU.
    36  	DiskImage string
    37  	Board     string
    38  
    39  	// BIOSImage is name of the BIOS file to pass to QEMU.
    40  	// It can be a plain name, or a full path.
    41  	BIOSImage string
    42  
    43  	// Don't modify CL disk images to add console logging
    44  	UseVanillaImage bool
    45  
    46  	*platform.Options
    47  }
    48  
    49  type flight struct {
    50  	*local.LocalFlight
    51  	opts *Options
    52  
    53  	diskImagePath string
    54  	diskImageFile *os.File
    55  }
    56  
    57  var (
    58  	plog = capnslog.NewPackageLogger("github.com/coreos/mantle", "platform/machine/qemu")
    59  )
    60  
    61  func NewFlight(opts *Options) (platform.Flight, error) {
    62  	lf, err := local.NewLocalFlight(opts.Options, Platform)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	qf := &flight{
    68  		LocalFlight:   lf,
    69  		opts:          opts,
    70  		diskImagePath: opts.DiskImage,
    71  	}
    72  
    73  	if opts.Distribution != "cl" {
    74  		// don't apply CL-specific mangling
    75  		opts.UseVanillaImage = true
    76  	}
    77  	if !opts.UseVanillaImage {
    78  		info, err := util.GetImageInfo(opts.DiskImage)
    79  		if err != nil {
    80  			qf.Destroy()
    81  			return nil, err
    82  		}
    83  		if info.Format != "raw" {
    84  			// platform.MakeCLDiskTemplate() needs to be able to mount
    85  			// partitions
    86  			plog.Debug("disk image is in qcow format; not enabling console logging")
    87  			opts.UseVanillaImage = true
    88  		}
    89  	}
    90  	if !opts.UseVanillaImage {
    91  		plog.Debug("enabling console logging in base disk")
    92  		qf.diskImageFile, err = platform.MakeCLDiskTemplate(opts.DiskImage)
    93  		if err != nil {
    94  			qf.Destroy()
    95  			return nil, err
    96  		}
    97  		// The template file has already been deleted, ensuring that
    98  		// it will be cleaned up on exit.  Use a path to it that
    99  		// will remain stable for the lifetime of the flight without
   100  		// extra effort to pass FDs to subprocesses.
   101  		qf.diskImagePath = fmt.Sprintf("/proc/%d/fd/%d", os.Getpid(), qf.diskImageFile.Fd())
   102  	}
   103  
   104  	return qf, nil
   105  }
   106  
   107  // NewCluster creates a Cluster instance, suitable for running virtual
   108  // machines in QEMU.
   109  func (qf *flight) NewCluster(rconf *platform.RuntimeConfig) (platform.Cluster, error) {
   110  	lc, err := qf.LocalFlight.NewCluster(rconf)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  
   115  	qc := &Cluster{
   116  		flight:       qf,
   117  		LocalCluster: lc,
   118  	}
   119  
   120  	qf.AddCluster(qc)
   121  
   122  	return qc, nil
   123  }
   124  
   125  func (qf *flight) Destroy() {
   126  	qf.LocalFlight.Destroy()
   127  	if qf.diskImageFile != nil {
   128  		qf.diskImageFile.Close()
   129  	}
   130  }