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  }