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 }