github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/worker/provisioner/kvm-broker.go (about) 1 // Copyright 2013 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/container/kvm" 14 "github.com/juju/juju/environs" 15 "github.com/juju/juju/instance" 16 ) 17 18 var kvmLogger = loggo.GetLogger("juju.provisioner.kvm") 19 20 var _ environs.InstanceBroker = (*kvmBroker)(nil) 21 22 func NewKvmBroker( 23 api APICalls, 24 agentConfig agent.Config, 25 managerConfig container.ManagerConfig, 26 enableNAT bool, 27 ) (environs.InstanceBroker, error) { 28 manager, err := kvm.NewContainerManager(managerConfig) 29 if err != nil { 30 return nil, err 31 } 32 return &kvmBroker{ 33 manager: manager, 34 api: api, 35 agentConfig: agentConfig, 36 enableNAT: enableNAT, 37 }, nil 38 } 39 40 type kvmBroker struct { 41 manager container.Manager 42 api APICalls 43 agentConfig agent.Config 44 enableNAT bool 45 } 46 47 // StartInstance is specified in the Broker interface. 48 func (broker *kvmBroker) StartInstance(args environs.StartInstanceParams) (*environs.StartInstanceResult, error) { 49 if args.InstanceConfig.HasNetworks() { 50 return nil, errors.New("starting kvm containers with networks is not supported yet") 51 } 52 // TODO: refactor common code out of the container brokers. 53 machineId := args.InstanceConfig.MachineId 54 kvmLogger.Infof("starting kvm container for machineId: %s", machineId) 55 56 // TODO: Default to using the host network until we can configure. Yes, 57 // this is using the LxcBridge value, we should put it in the api call for 58 // container config. 59 bridgeDevice := broker.agentConfig.Value(agent.LxcBridge) 60 if bridgeDevice == "" { 61 bridgeDevice = kvm.DefaultKvmBridge 62 } 63 if !environs.AddressAllocationEnabled() { 64 logger.Debugf( 65 "address allocation feature flag not enabled; using DHCP for container %q", 66 machineId, 67 ) 68 } else { 69 logger.Debugf("trying to allocate static IP for container %q", machineId) 70 71 allocatedInfo, err := configureContainerNetwork( 72 machineId, 73 bridgeDevice, 74 broker.api, 75 args.NetworkInfo, 76 true, // allocate a new address. 77 broker.enableNAT, 78 ) 79 if err != nil { 80 // It's fine, just ignore it. The effect will be that the 81 // container won't have a static address configured. 82 logger.Infof("not allocating static IP for container %q: %v", machineId, err) 83 } else { 84 args.NetworkInfo = allocatedInfo 85 } 86 } 87 88 // Unlike with LXC, we don't override the default MTU to use. 89 network := container.BridgeNetworkConfig(bridgeDevice, 0, args.NetworkInfo) 90 91 series := args.Tools.OneSeries() 92 args.InstanceConfig.MachineContainerType = instance.KVM 93 args.InstanceConfig.Tools = args.Tools[0] 94 95 config, err := broker.api.ContainerConfig() 96 if err != nil { 97 kvmLogger.Errorf("failed to get container config: %v", err) 98 return nil, err 99 } 100 101 if err := instancecfg.PopulateInstanceConfig( 102 args.InstanceConfig, 103 config.ProviderType, 104 config.AuthorizedKeys, 105 config.SSLHostnameVerification, 106 config.Proxy, 107 config.AptProxy, 108 config.AptMirror, 109 config.PreferIPv6, 110 config.EnableOSRefreshUpdate, 111 config.EnableOSUpgrade, 112 ); err != nil { 113 kvmLogger.Errorf("failed to populate machine config: %v", err) 114 return nil, err 115 } 116 117 storageConfig := &container.StorageConfig{ 118 AllowMount: true, 119 } 120 inst, hardware, err := broker.manager.CreateContainer(args.InstanceConfig, series, network, storageConfig) 121 if err != nil { 122 kvmLogger.Errorf("failed to start container: %v", err) 123 return nil, err 124 } 125 kvmLogger.Infof("started kvm container for machineId: %s, %s, %s", machineId, inst.Id(), hardware.String()) 126 return &environs.StartInstanceResult{ 127 Instance: inst, 128 Hardware: hardware, 129 }, nil 130 } 131 132 // StopInstances shuts down the given instances. 133 func (broker *kvmBroker) StopInstances(ids ...instance.Id) error { 134 // TODO: potentially parallelise. 135 for _, id := range ids { 136 kvmLogger.Infof("stopping kvm container for instance: %s", id) 137 if err := broker.manager.DestroyContainer(id); err != nil { 138 kvmLogger.Errorf("container did not stop: %v", err) 139 return err 140 } 141 } 142 return nil 143 } 144 145 // AllInstances only returns running containers. 146 func (broker *kvmBroker) AllInstances() (result []instance.Instance, err error) { 147 return broker.manager.ListContainers() 148 } 149 150 // MaintainInstance checks that the container's host has the required iptables and routing 151 // rules to make the container visible to both the host and other machines on the same subnet. 152 func (broker *kvmBroker) MaintainInstance(args environs.StartInstanceParams) error { 153 machineId := args.InstanceConfig.MachineId 154 if !environs.AddressAllocationEnabled() { 155 kvmLogger.Debugf("address allocation disabled: Not running maintenance for kvm with machineId: %s", 156 machineId) 157 return nil 158 } 159 160 kvmLogger.Debugf("running maintenance for kvm with machineId: %s", machineId) 161 162 // Default to using the host network until we can configure. 163 bridgeDevice := broker.agentConfig.Value(agent.LxcBridge) 164 if bridgeDevice == "" { 165 bridgeDevice = kvm.DefaultKvmBridge 166 } 167 _, err := configureContainerNetwork( 168 machineId, 169 bridgeDevice, 170 broker.api, 171 args.NetworkInfo, 172 false, // don't allocate a new address. 173 broker.enableNAT, 174 ) 175 return err 176 }