github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/network/netplan/activate.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package netplan 5 6 import ( 7 "fmt" 8 "os" 9 "time" 10 11 "github.com/juju/clock" 12 "github.com/juju/errors" 13 "github.com/juju/loggo" 14 15 "github.com/juju/juju/utils/scriptrunner" 16 ) 17 18 var logger = loggo.GetLogger("juju.network.netplan") 19 20 // ActivationParams contains options to use when bridging interfaces 21 type ActivationParams struct { 22 Clock clock.Clock 23 Devices []DeviceToBridge 24 RunPrefix string 25 Directory string 26 Timeout time.Duration 27 } 28 29 // ActivationResult captures the result of actively bridging the 30 // interfaces using ifup/ifdown. 31 type ActivationResult struct { 32 Stdout string 33 Stderr string 34 Code int 35 } 36 37 // BridgeAndActivate will parse a set of netplan yaml files in a directory, 38 // create a new netplan config with the provided interfaces bridged 39 // bridged, then reconfigure the network using the ifupdown package 40 // for the new bridges. 41 func BridgeAndActivate(params ActivationParams) (*ActivationResult, error) { 42 if len(params.Devices) == 0 { 43 return nil, errors.Errorf("no devices specified") 44 } 45 46 netplan, err := ReadDirectory(params.Directory) 47 48 if err != nil { 49 return nil, err 50 } 51 52 for _, device := range params.Devices { 53 var deviceId string 54 deviceId, deviceType, err := netplan.FindDeviceByNameOrMAC(device.DeviceName, device.MACAddress) 55 if err != nil { 56 return nil, errors.Trace(err) 57 } 58 switch deviceType { 59 case TypeEthernet: 60 err = netplan.BridgeEthernetById(deviceId, device.BridgeName) 61 if err != nil { 62 return nil, err 63 } 64 case TypeBond: 65 err = netplan.BridgeBondById(deviceId, device.BridgeName) 66 if err != nil { 67 return nil, err 68 } 69 case TypeVLAN: 70 err = netplan.BridgeVLANById(deviceId, device.BridgeName) 71 if err != nil { 72 return nil, err 73 } 74 default: 75 return nil, errors.Errorf("unable to create bridge for %q, unknown device type %q", deviceId, deviceType) 76 } 77 } 78 _, err = netplan.Write("") 79 if err != nil { 80 return nil, err 81 } 82 83 err = netplan.MoveYamlsToBak() 84 if err != nil { 85 netplan.Rollback() 86 return nil, err 87 } 88 89 environ := os.Environ() 90 // TODO(wpk) 2017-06-21 Is there a way to verify that apply is finished? 91 // https://bugs.launchpad.net/netplan/+bug/1701436 92 command := fmt.Sprintf("%snetplan generate && netplan apply && sleep 10", params.RunPrefix) 93 94 result, err := scriptrunner.RunCommand(command, environ, params.Clock, params.Timeout) 95 96 activationResult := ActivationResult{ 97 Stderr: string(result.Stderr), 98 Stdout: string(result.Stdout), 99 Code: result.Code, 100 } 101 102 logger.Debugf("Netplan activation result %q %q %d", result.Stderr, result.Stdout, result.Code) 103 104 if err != nil { 105 netplan.Rollback() 106 return &activationResult, errors.Errorf("bridge activation error: %s", err) 107 } 108 if result.Code != 0 { 109 netplan.Rollback() 110 return &activationResult, errors.Errorf("bridge activation error code %d", result.Code) 111 } 112 return nil, nil 113 }