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 = &params.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  }