github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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/names" 9 "github.com/juju/version" 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 25 facade base.FacadeCaller 26 } 27 28 const provisionerFacade = "Provisioner" 29 30 // NewState creates a new client-side Machiner facade. 31 func NewState(caller base.APICaller) *State { 32 facadeCaller := base.NewFacadeCaller(caller, provisionerFacade) 33 return &State{ 34 ModelWatcher: common.NewModelWatcher(facadeCaller), 35 APIAddresser: common.NewAPIAddresser(facadeCaller), 36 facade: facadeCaller} 37 } 38 39 // machineLife requests the lifecycle of the given machine from the server. 40 func (st *State) machineLife(tag names.MachineTag) (params.Life, error) { 41 return common.Life(st.facade, tag) 42 } 43 44 // Machine provides access to methods of a state.Machine through the facade. 45 func (st *State) Machine(tag names.MachineTag) (*Machine, error) { 46 life, err := st.machineLife(tag) 47 if err != nil { 48 return nil, err 49 } 50 return &Machine{ 51 tag: tag, 52 life: life, 53 st: st, 54 }, nil 55 } 56 57 // WatchModelMachines returns a StringsWatcher that notifies of 58 // changes to the lifecycles of the machines (but not containers) in 59 // the current model. 60 func (st *State) WatchModelMachines() (watcher.StringsWatcher, error) { 61 var result params.StringsWatchResult 62 err := st.facade.FacadeCall("WatchModelMachines", nil, &result) 63 if err != nil { 64 return nil, err 65 } 66 if err := result.Error; err != nil { 67 return nil, result.Error 68 } 69 w := apiwatcher.NewStringsWatcher(st.facade.RawAPICaller(), result) 70 return w, nil 71 } 72 73 func (st *State) WatchMachineErrorRetry() (watcher.NotifyWatcher, error) { 74 var result params.NotifyWatchResult 75 err := st.facade.FacadeCall("WatchMachineErrorRetry", nil, &result) 76 if err != nil { 77 return nil, err 78 } 79 if err := result.Error; err != nil { 80 return nil, result.Error 81 } 82 w := apiwatcher.NewNotifyWatcher(st.facade.RawAPICaller(), result) 83 return w, nil 84 } 85 86 // StateAddresses returns the list of addresses used to connect to the state. 87 func (st *State) StateAddresses() ([]string, error) { 88 var result params.StringsResult 89 err := st.facade.FacadeCall("StateAddresses", nil, &result) 90 if err != nil { 91 return nil, err 92 } 93 return result.Result, nil 94 } 95 96 // ContainerManagerConfig returns information from the model config that is 97 // needed for configuring the container manager. 98 func (st *State) ContainerManagerConfig(args params.ContainerManagerConfigParams) (result params.ContainerManagerConfig, err error) { 99 err = st.facade.FacadeCall("ContainerManagerConfig", args, &result) 100 return result, err 101 } 102 103 // ContainerConfig returns information from the model config that is 104 // needed for container cloud-init. 105 func (st *State) ContainerConfig() (result params.ContainerConfig, err error) { 106 err = st.facade.FacadeCall("ContainerConfig", nil, &result) 107 return result, err 108 } 109 110 // MachinesWithTransientErrors returns a slice of machines and corresponding status information 111 // for those machines which have transient provisioning errors. 112 func (st *State) MachinesWithTransientErrors() ([]*Machine, []params.StatusResult, error) { 113 var results params.StatusResults 114 err := st.facade.FacadeCall("MachinesWithTransientErrors", nil, &results) 115 if err != nil { 116 return nil, nil, err 117 } 118 machines := make([]*Machine, len(results.Results)) 119 for i, status := range results.Results { 120 if status.Error != nil { 121 continue 122 } 123 machines[i] = &Machine{ 124 tag: names.NewMachineTag(status.Id), 125 life: status.Life, 126 st: st, 127 } 128 } 129 return machines, results.Results, nil 130 } 131 132 // FindTools returns al ist of tools matching the specified version number and 133 // series, and, arch. If arch is blank, a default will be used. 134 func (st *State) FindTools(v version.Number, series string, arch string) (tools.List, error) { 135 args := params.FindToolsParams{ 136 Number: v, 137 Series: series, 138 MajorVersion: -1, 139 MinorVersion: -1, 140 } 141 if arch != "" { 142 args.Arch = arch 143 } 144 var result params.FindToolsResult 145 if err := st.facade.FacadeCall("FindTools", args, &result); err != nil { 146 return nil, err 147 } 148 if result.Error != nil { 149 return nil, result.Error 150 } 151 return result.List, nil 152 } 153 154 // ReleaseContainerAddresses releases a static IP address allocated to a 155 // container. 156 func (st *State) ReleaseContainerAddresses(containerTag names.MachineTag) (err error) { 157 defer errors.DeferredAnnotatef(&err, "cannot release static addresses for %q", containerTag.Id()) 158 var result params.ErrorResults 159 args := params.Entities{ 160 Entities: []params.Entity{{Tag: containerTag.String()}}, 161 } 162 if err := st.facade.FacadeCall("ReleaseContainerAddresses", args, &result); err != nil { 163 return err 164 } 165 return result.OneError() 166 } 167 168 // PrepareContainerInterfaceInfo allocates an address and returns 169 // information to configure networking for a container. It accepts 170 // container tags as arguments. If the address allocation feature flag 171 // is not enabled, it returns a NotSupported error. 172 func (st *State) PrepareContainerInterfaceInfo(containerTag names.MachineTag) ([]network.InterfaceInfo, error) { 173 return st.prepareOrGetContainerInterfaceInfo(containerTag, true) 174 } 175 176 // GetContainerInterfaceInfo returns information to configure networking 177 // for a container. It accepts container tags as arguments. If the address 178 // allocation feature flag is not enabled, it returns a NotSupported error. 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 }