github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/container/kvm/container.go (about) 1 // Copyright 2013-2106 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package kvm 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 "github.com/juju/utils/arch" 11 12 "github.com/juju/juju/container" 13 "github.com/juju/juju/container/kvm/libvirt" 14 "github.com/juju/juju/core/status" 15 "github.com/juju/juju/environs/imagedownloads" 16 "github.com/juju/juju/environs/simplestreams" 17 "github.com/juju/juju/network" 18 ) 19 20 type kvmContainer struct { 21 factory *containerFactory 22 name string 23 // started is a three state boolean, true, false, or unknown 24 // this allows for checking when we don't know, but using a 25 // value if we already know it (like in the list situation). 26 started *bool 27 28 pathfinder func(string) (string, error) 29 runCmd runFunc 30 } 31 32 var _ Container = (*kvmContainer)(nil) 33 34 func (c *kvmContainer) Name() string { 35 return c.name 36 } 37 38 func (c *kvmContainer) Start(params StartParams) error { 39 var srcFunc func() simplestreams.DataSource 40 if params.ImageDownloadURL != "" { 41 srcFunc = func() simplestreams.DataSource { 42 return imagedownloads.NewDataSource(params.ImageDownloadURL) 43 } 44 } 45 var ftype = BIOSFType 46 if params.Arch == arch.ARM64 { 47 ftype = UEFIFType 48 } 49 50 sp := syncParams{ 51 arch: params.Arch, 52 series: params.Series, 53 stream: params.Stream, 54 ftype: ftype, 55 srcFunc: srcFunc, 56 } 57 logger.Debugf("synchronise images for %s %s %s %s", sp.arch, sp.series, sp.stream, params.ImageDownloadURL) 58 var callback ProgressCallback 59 if params.StatusCallback != nil { 60 callback = func(msg string) { 61 params.StatusCallback(status.Provisioning, msg, nil) 62 } 63 } 64 if err := Sync(sp, nil, callback); err != nil { 65 if !errors.IsAlreadyExists(err) { 66 return errors.Trace(err) 67 } 68 logger.Debugf("image already cached %s", err) 69 } 70 var bridge string 71 var interfaces []libvirt.InterfaceInfo 72 if params.Network != nil { 73 if params.Network.NetworkType == container.BridgeNetwork { 74 bridge = params.Network.Device 75 for _, iface := range params.Network.Interfaces { 76 interfaces = append(interfaces, interfaceInfo{config: iface}) 77 } 78 } else { 79 err := errors.New("Non-bridge network devices not yet supported") 80 logger.Infof(err.Error()) 81 return err 82 } 83 } 84 logger.Debugf("create the machine %s", c.name) 85 if params.StatusCallback != nil { 86 params.StatusCallback(status.Provisioning, "Creating instance", nil) 87 } 88 if err := CreateMachine(CreateMachineParams{ 89 Hostname: c.name, 90 Series: params.Series, 91 UserDataFile: params.UserDataFile, 92 NetworkConfigData: params.NetworkConfigData, 93 NetworkBridge: bridge, 94 Memory: params.Memory, 95 CpuCores: params.CpuCores, 96 RootDisk: params.RootDisk, 97 Interfaces: interfaces, 98 }); err != nil { 99 return err 100 } 101 102 logger.Debugf("Set machine %s to autostart", c.name) 103 if params.StatusCallback != nil { 104 params.StatusCallback(status.Provisioning, "Starting instance", nil) 105 } 106 return AutostartMachine(c) 107 } 108 109 func (c *kvmContainer) Stop() error { 110 if !c.IsRunning() { 111 logger.Debugf("%s is already stopped", c.name) 112 return nil 113 } 114 // Make started state unknown again. 115 c.started = nil 116 logger.Debugf("Stop %s", c) 117 118 return DestroyMachine(c) 119 } 120 121 func (c *kvmContainer) IsRunning() bool { 122 if c.started != nil { 123 return *c.started 124 } 125 machines, err := ListMachines(run) 126 if err != nil { 127 return false 128 } 129 c.started = isRunning(machines[c.name]) 130 return *c.started 131 } 132 133 func (c *kvmContainer) String() string { 134 return fmt.Sprintf("<KVM container %v>", *c) 135 } 136 137 type interfaceInfo struct { 138 config network.InterfaceInfo 139 } 140 141 // MACAddress returns the embedded MacAddress value. 142 func (i interfaceInfo) MACAddress() string { 143 return i.config.MACAddress 144 } 145 146 // InterfaceName returns the embedded InterfaceName value. 147 func (i interfaceInfo) InterfaceName() string { 148 return i.config.InterfaceName 149 } 150 151 // ParentInterfaceName returns the embedded ParentInterfaceName value. 152 func (i interfaceInfo) ParentInterfaceName() string { 153 return i.config.ParentInterfaceName 154 }