github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/api/provisioner/provisioner.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/version" 9 "gopkg.in/juju/names.v2" 10 11 "github.com/juju/juju/api/base" 12 "github.com/juju/juju/api/common" 13 apiwatcher "github.com/juju/juju/api/watcher" 14 "github.com/juju/juju/apiserver/params" 15 "github.com/juju/juju/network" 16 "github.com/juju/juju/tools" 17 "github.com/juju/juju/watcher" 18 ) 19 20 // State provides access to the Machiner API facade. 21 type State struct { 22 *common.ModelWatcher 23 *common.APIAddresser 24 *common.ControllerConfigAPI 25 26 facade base.FacadeCaller 27 } 28 29 const provisionerFacade = "Provisioner" 30 31 // NewState creates a new client-side Machiner facade. 32 func NewState(caller base.APICaller) *State { 33 facadeCaller := base.NewFacadeCaller(caller, provisionerFacade) 34 return &State{ 35 ModelWatcher: common.NewModelWatcher(facadeCaller), 36 APIAddresser: common.NewAPIAddresser(facadeCaller), 37 ControllerConfigAPI: common.NewControllerConfig(facadeCaller), 38 facade: facadeCaller, 39 } 40 } 41 42 // machineLife requests the lifecycle of the given machine from the server. 43 func (st *State) machineLife(tag names.MachineTag) (params.Life, error) { 44 return common.Life(st.facade, tag) 45 } 46 47 // Machine provides access to methods of a state.Machine through the facade. 48 func (st *State) Machine(tag names.MachineTag) (*Machine, error) { 49 life, err := st.machineLife(tag) 50 if err != nil { 51 return nil, err 52 } 53 return &Machine{ 54 tag: tag, 55 life: life, 56 st: st, 57 }, nil 58 } 59 60 // WatchModelMachines returns a StringsWatcher that notifies of 61 // changes to the lifecycles of the machines (but not containers) in 62 // the current model. 63 func (st *State) WatchModelMachines() (watcher.StringsWatcher, error) { 64 var result params.StringsWatchResult 65 err := st.facade.FacadeCall("WatchModelMachines", nil, &result) 66 if err != nil { 67 return nil, err 68 } 69 if err := result.Error; err != nil { 70 return nil, result.Error 71 } 72 w := apiwatcher.NewStringsWatcher(st.facade.RawAPICaller(), result) 73 return w, nil 74 } 75 76 func (st *State) WatchMachineErrorRetry() (watcher.NotifyWatcher, error) { 77 var result params.NotifyWatchResult 78 err := st.facade.FacadeCall("WatchMachineErrorRetry", nil, &result) 79 if err != nil { 80 return nil, err 81 } 82 if err := result.Error; err != nil { 83 return nil, result.Error 84 } 85 w := apiwatcher.NewNotifyWatcher(st.facade.RawAPICaller(), result) 86 return w, nil 87 } 88 89 // StateAddresses returns the list of addresses used to connect to the state. 90 func (st *State) StateAddresses() ([]string, error) { 91 var result params.StringsResult 92 err := st.facade.FacadeCall("StateAddresses", nil, &result) 93 if err != nil { 94 return nil, err 95 } 96 return result.Result, nil 97 } 98 99 // ContainerManagerConfig returns information from the model config that is 100 // needed for configuring the container manager. 101 func (st *State) ContainerManagerConfig(args params.ContainerManagerConfigParams) (result params.ContainerManagerConfig, err error) { 102 err = st.facade.FacadeCall("ContainerManagerConfig", args, &result) 103 return result, err 104 } 105 106 // ContainerConfig returns information from the model config that is 107 // needed for container cloud-init. 108 func (st *State) ContainerConfig() (result params.ContainerConfig, err error) { 109 err = st.facade.FacadeCall("ContainerConfig", nil, &result) 110 return result, err 111 } 112 113 // MachinesWithTransientErrors returns a slice of machines and corresponding status information 114 // for those machines which have transient provisioning errors. 115 func (st *State) MachinesWithTransientErrors() ([]*Machine, []params.StatusResult, error) { 116 var results params.StatusResults 117 err := st.facade.FacadeCall("MachinesWithTransientErrors", nil, &results) 118 if err != nil { 119 return nil, nil, err 120 } 121 machines := make([]*Machine, len(results.Results)) 122 for i, status := range results.Results { 123 if status.Error != nil { 124 continue 125 } 126 machines[i] = &Machine{ 127 tag: names.NewMachineTag(status.Id), 128 life: status.Life, 129 st: st, 130 } 131 } 132 return machines, results.Results, nil 133 } 134 135 // FindTools returns al ist of tools matching the specified version number and 136 // series, and, arch. If arch is blank, a default will be used. 137 func (st *State) FindTools(v version.Number, series string, arch string) (tools.List, error) { 138 args := params.FindToolsParams{ 139 Number: v, 140 Series: series, 141 MajorVersion: -1, 142 MinorVersion: -1, 143 } 144 if arch != "" { 145 args.Arch = arch 146 } 147 var result params.FindToolsResult 148 if err := st.facade.FacadeCall("FindTools", args, &result); err != nil { 149 return nil, err 150 } 151 if result.Error != nil { 152 return nil, result.Error 153 } 154 return result.List, nil 155 } 156 157 // ReleaseContainerAddresses releases a static IP address allocated to a 158 // container. 159 func (st *State) ReleaseContainerAddresses(containerTag names.MachineTag) (err error) { 160 defer errors.DeferredAnnotatef(&err, "cannot release static addresses for %q", containerTag.Id()) 161 var result params.ErrorResults 162 args := params.Entities{ 163 Entities: []params.Entity{{Tag: containerTag.String()}}, 164 } 165 if err := st.facade.FacadeCall("ReleaseContainerAddresses", args, &result); err != nil { 166 return err 167 } 168 return result.OneError() 169 } 170 171 // PrepareContainerInterfaceInfo allocates an address and returns information to 172 // configure networking for a container. It accepts container tags as arguments. 173 func (st *State) PrepareContainerInterfaceInfo(containerTag names.MachineTag) ([]network.InterfaceInfo, error) { 174 return st.prepareOrGetContainerInterfaceInfo(containerTag, true) 175 } 176 177 // GetContainerInterfaceInfo returns information to configure networking 178 // for a container. It accepts container tags as arguments. 179 func (st *State) GetContainerInterfaceInfo(containerTag names.MachineTag) ([]network.InterfaceInfo, error) { 180 return st.prepareOrGetContainerInterfaceInfo(containerTag, false) 181 } 182 183 // prepareOrGetContainerInterfaceInfo returns the necessary information to 184 // configure network interfaces of a container with allocated static 185 // IP addresses. 186 // 187 // TODO(dimitern): Before we start using this, we need to rename both 188 // the method and the network.InterfaceInfo type to be called 189 // InterfaceConfig. 190 func (st *State) prepareOrGetContainerInterfaceInfo( 191 containerTag names.MachineTag, allocateNewAddress bool) ( 192 []network.InterfaceInfo, error) { 193 var result params.MachineNetworkConfigResults 194 args := params.Entities{ 195 Entities: []params.Entity{{Tag: containerTag.String()}}, 196 } 197 facadeName := "" 198 if allocateNewAddress { 199 facadeName = "PrepareContainerInterfaceInfo" 200 } else { 201 facadeName = "GetContainerInterfaceInfo" 202 } 203 if err := st.facade.FacadeCall(facadeName, args, &result); err != nil { 204 return nil, err 205 } 206 if len(result.Results) != 1 { 207 return nil, errors.Errorf("expected 1 result, got %d", len(result.Results)) 208 } 209 if err := result.Results[0].Error; err != nil { 210 return nil, err 211 } 212 ifaceInfo := make([]network.InterfaceInfo, len(result.Results[0].Config)) 213 for i, cfg := range result.Results[0].Config { 214 ifaceInfo[i] = network.InterfaceInfo{ 215 DeviceIndex: cfg.DeviceIndex, 216 MACAddress: cfg.MACAddress, 217 CIDR: cfg.CIDR, 218 MTU: cfg.MTU, 219 ProviderId: network.Id(cfg.ProviderId), 220 ProviderSubnetId: network.Id(cfg.ProviderSubnetId), 221 ProviderSpaceId: network.Id(cfg.ProviderSpaceId), 222 ProviderVLANId: network.Id(cfg.ProviderVLANId), 223 ProviderAddressId: network.Id(cfg.ProviderAddressId), 224 VLANTag: cfg.VLANTag, 225 InterfaceName: cfg.InterfaceName, 226 ParentInterfaceName: cfg.ParentInterfaceName, 227 InterfaceType: network.InterfaceType(cfg.InterfaceType), 228 Disabled: cfg.Disabled, 229 NoAutoStart: cfg.NoAutoStart, 230 ConfigType: network.InterfaceConfigType(cfg.ConfigType), 231 Address: network.NewAddress(cfg.Address), 232 DNSServers: network.NewAddresses(cfg.DNSServers...), 233 DNSSearchDomains: cfg.DNSSearchDomains, 234 GatewayAddress: network.NewAddress(cfg.GatewayAddress), 235 } 236 } 237 return ifaceInfo, nil 238 }