github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/container/broker/host_preparer.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package broker 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 "github.com/juju/names/v5" 10 11 "github.com/juju/juju/network" 12 "github.com/juju/juju/rpc/params" 13 ) 14 15 // PrepareAPI is the functional interface that we need to be able to ask what 16 // changes are necessary, and to then report back what changes have been done 17 // to the host machine. 18 type PrepareAPI interface { 19 // HostChangesForContainer returns the list of bridges to be created on the 20 // host machine, and the time to sleep after creating the bridges before 21 // bringing them up. 22 HostChangesForContainer(names.MachineTag) ([]network.DeviceToBridge, int, error) 23 // SetHostMachineNetworkConfig allows us to report back the host machine's 24 // current networking config. This is called after we've created new 25 // bridges to inform the Controller what the current networking interfaces 26 // are. 27 SetHostMachineNetworkConfig(names.MachineTag, []params.NetworkConfig) error 28 } 29 30 // HostPreparerParams is the configuration for HostPreparer 31 type HostPreparerParams struct { 32 API PrepareAPI 33 ObserveNetworkFunc func() ([]params.NetworkConfig, error) 34 AcquireLockFunc func(string, <-chan struct{}) (func(), error) 35 CreateBridger func() (network.Bridger, error) 36 AbortChan <-chan struct{} 37 MachineTag names.MachineTag 38 Logger loggo.Logger 39 } 40 41 // HostPreparer calls out to the PrepareAPI to find out what changes need to be 42 // done on this host to allow a new container to be started. 43 type HostPreparer struct { 44 api PrepareAPI 45 observeNetworkFunc func() ([]params.NetworkConfig, error) 46 acquireLockFunc func(string, <-chan struct{}) (func(), error) 47 createBridger func() (network.Bridger, error) 48 abortChan <-chan struct{} 49 machineTag names.MachineTag 50 logger loggo.Logger 51 } 52 53 // NewHostPreparer creates a HostPreparer using the supplied parameters 54 func NewHostPreparer(params HostPreparerParams) *HostPreparer { 55 return &HostPreparer{ 56 api: params.API, 57 observeNetworkFunc: params.ObserveNetworkFunc, 58 acquireLockFunc: params.AcquireLockFunc, 59 createBridger: params.CreateBridger, 60 abortChan: params.AbortChan, 61 machineTag: params.MachineTag, 62 logger: params.Logger, 63 } 64 } 65 66 // Prepare applies changes to the host machine that are necessary to create 67 // the requested container. 68 func (hp *HostPreparer) Prepare(containerTag names.MachineTag) error { 69 releaser, err := hp.acquireLockFunc("bridging devices", hp.abortChan) 70 if err != nil { 71 return errors.Annotatef(err, "failed to acquire machine lock for bridging") 72 } 73 defer releaser() 74 75 devicesToBridge, reconfigureDelay, err := hp.api.HostChangesForContainer(containerTag) 76 if err != nil { 77 return errors.Annotate(err, "unable to setup network") 78 } 79 80 if len(devicesToBridge) == 0 { 81 hp.logger.Debugf("container %q requires no additional bridges", containerTag) 82 return nil 83 } 84 85 bridger, err := hp.createBridger() 86 if err != nil { 87 return errors.Trace(err) 88 } 89 90 hp.logger.Debugf("bridging %+v devices on host %q for container %q with delay=%v", 91 devicesToBridge, hp.machineTag.String(), containerTag.String(), reconfigureDelay) 92 93 // TODO(jam): 2017-02-15 bridger.Bridge should probably also take AbortChan 94 // if it is going to have reconfigureDelay 95 err = bridger.Bridge(devicesToBridge, reconfigureDelay) 96 if err != nil { 97 return errors.Annotate(err, "failed to bridge devices") 98 } 99 100 // We just changed the hosts' network setup so discover new 101 // interfaces/devices and propagate to state. 102 observedConfig, err := hp.observeNetworkFunc() 103 if err != nil { 104 return errors.Annotate(err, "cannot discover observed network config") 105 } 106 107 if len(observedConfig) > 0 { 108 hp.logger.Debugf("updating observed network config for %q to %#v", hp.machineTag.String(), observedConfig) 109 err := hp.api.SetHostMachineNetworkConfig(hp.machineTag, observedConfig) 110 if err != nil { 111 return errors.Trace(err) 112 } 113 } 114 115 return nil 116 }