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