github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/provisioner/lxd-broker.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provisioner 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 10 "github.com/juju/juju/agent" 11 "github.com/juju/juju/cloudconfig/instancecfg" 12 "github.com/juju/juju/container" 13 "github.com/juju/juju/environs" 14 "github.com/juju/juju/instance" 15 "github.com/juju/juju/network" 16 ) 17 18 var lxdLogger = loggo.GetLogger("juju.provisioner.lxd") 19 20 var NewLxdBroker = func( 21 api APICalls, 22 manager container.Manager, 23 agentConfig agent.Config, 24 ) (environs.InstanceBroker, error) { 25 return &lxdBroker{ 26 manager: manager, 27 api: api, 28 agentConfig: agentConfig, 29 }, nil 30 } 31 32 type lxdBroker struct { 33 manager container.Manager 34 api APICalls 35 agentConfig agent.Config 36 } 37 38 func (broker *lxdBroker) StartInstance(args environs.StartInstanceParams) (*environs.StartInstanceResult, error) { 39 machineId := args.InstanceConfig.MachineId 40 bridgeDevice := broker.agentConfig.Value(agent.LxdBridge) 41 if bridgeDevice == "" { 42 bridgeDevice = network.DefaultLXDBridge 43 } 44 45 config, err := broker.api.ContainerConfig() 46 if err != nil { 47 lxdLogger.Errorf("failed to get container config: %v", err) 48 return nil, err 49 } 50 51 preparedInfo, err := prepareOrGetContainerInterfaceInfo( 52 broker.api, 53 machineId, 54 bridgeDevice, 55 true, // allocate if possible, do not maintain existing. 56 args.NetworkInfo, 57 lxdLogger, 58 ) 59 if err != nil { 60 // It's not fatal (yet) if we couldn't pre-allocate addresses for the 61 // container. 62 logger.Warningf("failed to prepare container %q network config: %v", machineId, err) 63 } else { 64 args.NetworkInfo = preparedInfo 65 } 66 67 network := container.BridgeNetworkConfig(bridgeDevice, 0, args.NetworkInfo) 68 interfaces, err := finishNetworkConfig(bridgeDevice, args.NetworkInfo) 69 if err != nil { 70 return nil, errors.Trace(err) 71 } 72 network.Interfaces = interfaces 73 74 // The provisioner worker will provide all tools it knows about 75 // (after applying explicitly specified constraints), which may 76 // include tools for architectures other than the host's. We 77 // must constrain to the host's architecture for LXD. 78 archTools, err := matchHostArchTools(args.Tools) 79 if err != nil { 80 return nil, errors.Trace(err) 81 } 82 83 series := archTools.OneSeries() 84 args.InstanceConfig.MachineContainerType = instance.LXD 85 if err := args.InstanceConfig.SetTools(archTools); err != nil { 86 return nil, errors.Trace(err) 87 } 88 89 if err := instancecfg.PopulateInstanceConfig( 90 args.InstanceConfig, 91 config.ProviderType, 92 config.AuthorizedKeys, 93 config.SSLHostnameVerification, 94 config.Proxy, 95 config.AptProxy, 96 config.AptMirror, 97 config.EnableOSRefreshUpdate, 98 config.EnableOSUpgrade, 99 ); err != nil { 100 lxdLogger.Errorf("failed to populate machine config: %v", err) 101 return nil, err 102 } 103 104 storageConfig := &container.StorageConfig{} 105 inst, hardware, err := broker.manager.CreateContainer( 106 args.InstanceConfig, args.Constraints, 107 series, network, storageConfig, args.StatusCallback, 108 ) 109 if err != nil { 110 return nil, err 111 } 112 113 return &environs.StartInstanceResult{ 114 Instance: inst, 115 Hardware: hardware, 116 NetworkInfo: interfaces, 117 }, nil 118 } 119 120 func (broker *lxdBroker) StopInstances(ids ...instance.Id) error { 121 // TODO: potentially parallelise. 122 for _, id := range ids { 123 lxdLogger.Infof("stopping lxd container for instance: %s", id) 124 if err := broker.manager.DestroyContainer(id); err != nil { 125 lxdLogger.Errorf("container did not stop: %v", err) 126 return err 127 } 128 releaseContainerAddresses(broker.api, id, broker.manager.Namespace(), lxdLogger) 129 } 130 return nil 131 } 132 133 // AllInstances only returns running containers. 134 func (broker *lxdBroker) AllInstances() (result []instance.Instance, err error) { 135 return broker.manager.ListContainers() 136 } 137 138 // MaintainInstance ensures the container's host has the required iptables and 139 // routing rules to make the container visible to both the host and other 140 // machines on the same subnet. 141 func (broker *lxdBroker) MaintainInstance(args environs.StartInstanceParams) error { 142 machineID := args.InstanceConfig.MachineId 143 144 // Default to using the host network until we can configure. 145 bridgeDevice := broker.agentConfig.Value(agent.LxdBridge) 146 if bridgeDevice == "" { 147 bridgeDevice = network.DefaultLXDBridge 148 } 149 150 // There's no InterfaceInfo we expect to get below. 151 _, err := prepareOrGetContainerInterfaceInfo( 152 broker.api, 153 machineID, 154 bridgeDevice, 155 false, // maintain, do not allocate. 156 args.NetworkInfo, 157 lxdLogger, 158 ) 159 return err 160 }