github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/client/machinemanager/machinemanager.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package machinemanager 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/names/v5" 11 12 "github.com/juju/juju/api/base" 13 apiwatcher "github.com/juju/juju/api/watcher" 14 apiservererrors "github.com/juju/juju/apiserver/errors" 15 "github.com/juju/juju/core/watcher" 16 "github.com/juju/juju/rpc/params" 17 ) 18 19 const machineManagerFacade = "MachineManager" 20 21 // Client provides access to the machinemanager, used to add machines to state. 22 type Client struct { 23 base.ClientFacade 24 facade base.FacadeCaller 25 } 26 27 // ConstructClient is a constructor function for a machine manager client 28 func ConstructClient(clientFacade base.ClientFacade, facadeCaller base.FacadeCaller) *Client { 29 return &Client{ClientFacade: clientFacade, facade: facadeCaller} 30 } 31 32 // NewClient returns a new machinemanager client. 33 func NewClient(st base.APICallCloser) *Client { 34 frontend, backend := base.NewClientFacade(st, machineManagerFacade) 35 return ConstructClient(frontend, backend) 36 } 37 38 // ModelUUID returns the model UUID from the client connection. 39 func (c *Client) ModelUUID() (string, bool) { 40 tag, ok := c.facade.RawAPICaller().ModelTag() 41 return tag.Id(), ok 42 } 43 44 // AddMachines adds new machines with the supplied parameters, creating any requested disks. 45 func (client *Client) AddMachines(machineParams []params.AddMachineParams) ([]params.AddMachinesResult, error) { 46 args := params.AddMachines{ 47 MachineParams: machineParams, 48 } 49 results := new(params.AddMachinesResults) 50 51 err := client.facade.FacadeCall("AddMachines", args, results) 52 if err != nil { 53 return nil, errors.Trace(err) 54 } 55 56 if len(results.Machines) != len(machineParams) { 57 return nil, errors.Errorf("expected %d result, got %d", len(machineParams), len(results.Machines)) 58 } 59 60 return results.Machines, nil 61 } 62 63 // DestroyMachinesWithParams removes the given set of machines, the semantics of which 64 // is determined by the force and keep parameters. 65 func (client *Client) DestroyMachinesWithParams(force, keep, dryRun bool, maxWait *time.Duration, machines ...string) ([]params.DestroyMachineResult, error) { 66 args := params.DestroyMachinesParams{ 67 Force: force, 68 Keep: keep, 69 DryRun: dryRun, 70 MachineTags: make([]string, 0, len(machines)), 71 MaxWait: maxWait, 72 } 73 allResults := make([]params.DestroyMachineResult, len(machines)) 74 index := make([]int, 0, len(machines)) 75 for i, machineId := range machines { 76 if !names.IsValidMachine(machineId) { 77 allResults[i].Error = ¶ms.Error{ 78 Message: errors.NotValidf("machine ID %q", machineId).Error(), 79 } 80 continue 81 } 82 index = append(index, i) 83 args.MachineTags = append(args.MachineTags, names.NewMachineTag(machineId).String()) 84 } 85 if len(args.MachineTags) > 0 { 86 var result params.DestroyMachineResults 87 if err := client.facade.FacadeCall("DestroyMachineWithParams", args, &result); err != nil { 88 return nil, errors.Trace(err) 89 } 90 if n := len(result.Results); n != len(args.MachineTags) { 91 return nil, errors.Errorf("expected %d result(s), got %d", len(args.MachineTags), n) 92 } 93 for i, result := range result.Results { 94 allResults[index[i]] = result 95 } 96 } 97 return allResults, nil 98 } 99 100 // ProvisioningScript returns a shell script that, when run, 101 // provisions a machine agent on the machine executing the script. 102 func (c *Client) ProvisioningScript(args params.ProvisioningScriptParams) (script string, err error) { 103 var result params.ProvisioningScriptResult 104 if err = c.facade.FacadeCall("ProvisioningScript", args, &result); err != nil { 105 return "", err 106 } 107 return result.Script, nil 108 } 109 110 // RetryProvisioning updates the provisioning status of a machine allowing the 111 // provisioner to retry. 112 func (c *Client) RetryProvisioning(all bool, machines ...names.MachineTag) ([]params.ErrorResult, error) { 113 p := params.RetryProvisioningArgs{ 114 All: all, 115 } 116 p.Machines = make([]string, len(machines)) 117 for i, machine := range machines { 118 p.Machines[i] = machine.String() 119 } 120 var results params.ErrorResults 121 err := c.facade.FacadeCall("RetryProvisioning", p, &results) 122 return results.Results, err 123 } 124 125 // UpgradeSeriesPrepare notifies the controller that a series upgrade is taking 126 // place for a given machine and as such the machine is guarded against 127 // operations that would impede, fail, or interfere with the upgrade process. 128 func (client *Client) UpgradeSeriesPrepare(machineName, channel string, force bool) error { 129 args := params.UpdateChannelArg{ 130 Entity: params.Entity{ 131 Tag: names.NewMachineTag(machineName).String(), 132 }, 133 Channel: channel, 134 Force: force, 135 } 136 var result params.ErrorResult 137 if err := client.facade.FacadeCall("UpgradeSeriesPrepare", args, &result); err != nil { 138 return errors.Trace(err) 139 } 140 141 if err := result.Error; err != nil { 142 return apiservererrors.RestoreError(err) 143 } 144 return nil 145 } 146 147 // UpgradeSeriesComplete notifies the controller that a given machine has 148 // successfully completed the managed series upgrade process. 149 func (client *Client) UpgradeSeriesComplete(machineName string) error { 150 args := params.UpdateChannelArg{ 151 Entity: params.Entity{Tag: names.NewMachineTag(machineName).String()}, 152 } 153 result := new(params.ErrorResult) 154 err := client.facade.FacadeCall("UpgradeSeriesComplete", args, result) 155 if err != nil { 156 return errors.Trace(err) 157 } 158 if result.Error != nil { 159 return result.Error 160 } 161 162 return nil 163 } 164 165 func (client *Client) UpgradeSeriesValidate(machineName, channel string) ([]string, error) { 166 args := params.UpdateChannelArgs{ 167 Args: []params.UpdateChannelArg{ 168 { 169 Entity: params.Entity{Tag: names.NewMachineTag(machineName).String()}, 170 Channel: channel, 171 }, 172 }, 173 } 174 results := new(params.UpgradeSeriesUnitsResults) 175 err := client.facade.FacadeCall("UpgradeSeriesValidate", args, results) 176 if err != nil { 177 return nil, err 178 } 179 if n := len(results.Results); n != 1 { 180 return nil, errors.Errorf("expected 1 result, got %d", n) 181 } 182 if results.Results[0].Error != nil { 183 return nil, results.Results[0].Error 184 } 185 return results.Results[0].UnitNames, nil 186 } 187 188 // WatchUpgradeSeriesNotifications returns a NotifyWatcher for observing the state of 189 // a series upgrade. 190 func (client *Client) WatchUpgradeSeriesNotifications(machineName string) (watcher.NotifyWatcher, string, error) { 191 var results params.NotifyWatchResults 192 args := params.Entities{ 193 Entities: []params.Entity{{Tag: names.NewMachineTag(machineName).String()}}, 194 } 195 err := client.facade.FacadeCall("WatchUpgradeSeriesNotifications", args, &results) 196 if err != nil { 197 return nil, "", errors.Trace(err) 198 } 199 if len(results.Results) != 1 { 200 return nil, "", errors.Errorf("expected 1 result, got %d", len(results.Results)) 201 } 202 result := results.Results[0] 203 if result.Error != nil { 204 return nil, "", result.Error 205 } 206 w := apiwatcher.NewNotifyWatcher(client.facade.RawAPICaller(), result) 207 return w, result.NotifyWatcherId, nil 208 } 209 210 // GetUpgradeSeriesMessages returns a StringsWatcher for observing the state of 211 // a series upgrade. 212 func (client *Client) GetUpgradeSeriesMessages(machineName, watcherId string) ([]string, error) { 213 var results params.StringsResults 214 args := params.UpgradeSeriesNotificationParams{ 215 Params: []params.UpgradeSeriesNotificationParam{ 216 { 217 Entity: params.Entity{Tag: names.NewMachineTag(machineName).String()}, 218 WatcherId: watcherId, 219 }, 220 }, 221 } 222 err := client.facade.FacadeCall("GetUpgradeSeriesMessages", args, &results) 223 if err != nil { 224 return nil, errors.Trace(err) 225 } 226 if len(results.Results) != 1 { 227 return nil, errors.Errorf("expected 1 result, got %d", len(results.Results)) 228 } 229 result := results.Results[0] 230 if result.Error != nil { 231 return nil, result.Error 232 } 233 234 return result.Result, nil 235 }