github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/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  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/api/base"
    11  	apiwatcher "github.com/juju/juju/api/watcher"
    12  	"github.com/juju/juju/apiserver/common"
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/core/watcher"
    15  )
    16  
    17  const machineManagerFacade = "MachineManager"
    18  
    19  // Client provides access to the machinemanager, used to add machines to state.
    20  type Client struct {
    21  	base.ClientFacade
    22  	facade base.FacadeCaller
    23  }
    24  
    25  // ConstructClient is a constructor function for a machine manager client
    26  func ConstructClient(clientFacade base.ClientFacade, facadeCaller base.FacadeCaller) *Client {
    27  	return &Client{ClientFacade: clientFacade, facade: facadeCaller}
    28  }
    29  
    30  // NewClient returns a new machinemanager client.
    31  func NewClient(st base.APICallCloser) *Client {
    32  	frontend, backend := base.NewClientFacade(st, machineManagerFacade)
    33  	return ConstructClient(frontend, backend)
    34  }
    35  
    36  // AddMachines adds new machines with the supplied parameters, creating any requested disks.
    37  func (client *Client) AddMachines(machineParams []params.AddMachineParams) ([]params.AddMachinesResult, error) {
    38  	args := params.AddMachines{
    39  		MachineParams: machineParams,
    40  	}
    41  	results := new(params.AddMachinesResults)
    42  	err := client.facade.FacadeCall("AddMachines", args, results)
    43  	if len(results.Machines) != len(machineParams) {
    44  		return nil, errors.Errorf("expected %d result, got %d", len(machineParams), len(results.Machines))
    45  	}
    46  	return results.Machines, err
    47  }
    48  
    49  // DestroyMachines removes a given set of machines.
    50  func (client *Client) DestroyMachines(machines ...string) ([]params.DestroyMachineResult, error) {
    51  	return client.destroyMachines("DestroyMachine", machines)
    52  }
    53  
    54  // ForceDestroyMachines removes a given set of machines and all
    55  // associated units.
    56  func (client *Client) ForceDestroyMachines(machines ...string) ([]params.DestroyMachineResult, error) {
    57  	return client.destroyMachines("ForceDestroyMachine", machines)
    58  }
    59  
    60  // DestroyMachinesWithParams removes the given set of machines, the semantics of which
    61  // is determined by the force and keep parameters.
    62  // TODO(wallyworld) - for Juju 3.0, this should be the preferred api to use.
    63  func (client *Client) DestroyMachinesWithParams(force, keep bool, machines ...string) ([]params.DestroyMachineResult, error) {
    64  	args := params.DestroyMachinesParams{
    65  		Force:       force,
    66  		Keep:        keep,
    67  		MachineTags: make([]string, 0, len(machines)),
    68  	}
    69  	allResults := make([]params.DestroyMachineResult, len(machines))
    70  	index := make([]int, 0, len(machines))
    71  	for i, machineId := range machines {
    72  		if !names.IsValidMachine(machineId) {
    73  			allResults[i].Error = &params.Error{
    74  				Message: errors.NotValidf("machine ID %q", machineId).Error(),
    75  			}
    76  			continue
    77  		}
    78  		index = append(index, i)
    79  		args.MachineTags = append(args.MachineTags, names.NewMachineTag(machineId).String())
    80  	}
    81  	if len(args.MachineTags) > 0 {
    82  		var result params.DestroyMachineResults
    83  		if err := client.facade.FacadeCall("DestroyMachineWithParams", args, &result); err != nil {
    84  			return nil, errors.Trace(err)
    85  		}
    86  		if n := len(result.Results); n != len(args.MachineTags) {
    87  			return nil, errors.Errorf("expected %d result(s), got %d", len(args.MachineTags), n)
    88  		}
    89  		for i, result := range result.Results {
    90  			allResults[index[i]] = result
    91  		}
    92  	}
    93  	return allResults, nil
    94  }
    95  
    96  func (client *Client) destroyMachines(method string, machines []string) ([]params.DestroyMachineResult, error) {
    97  	args := params.Entities{
    98  		Entities: make([]params.Entity, 0, len(machines)),
    99  	}
   100  	allResults := make([]params.DestroyMachineResult, len(machines))
   101  	index := make([]int, 0, len(machines))
   102  	for i, machineId := range machines {
   103  		if !names.IsValidMachine(machineId) {
   104  			allResults[i].Error = &params.Error{
   105  				Message: errors.NotValidf("machine ID %q", machineId).Error(),
   106  			}
   107  			continue
   108  		}
   109  		index = append(index, i)
   110  		args.Entities = append(args.Entities, params.Entity{
   111  			Tag: names.NewMachineTag(machineId).String(),
   112  		})
   113  	}
   114  	if len(args.Entities) > 0 {
   115  		var result params.DestroyMachineResults
   116  		if err := client.facade.FacadeCall(method, args, &result); err != nil {
   117  			return nil, errors.Trace(err)
   118  		}
   119  		if n := len(result.Results); n != len(args.Entities) {
   120  			return nil, errors.Errorf("expected %d result(s), got %d", len(args.Entities), n)
   121  		}
   122  		for i, result := range result.Results {
   123  			allResults[index[i]] = result
   124  		}
   125  	}
   126  	return allResults, nil
   127  }
   128  
   129  // UpgradeSeriesPrepare notifies the controller that a series upgrade is taking
   130  // place for a given machine and as such the machine is guarded against
   131  // operations that would impede, fail, or interfere with the upgrade process.
   132  func (client *Client) UpgradeSeriesPrepare(machineName, series string, force bool) error {
   133  	if client.BestAPIVersion() < 5 {
   134  		return errors.NotSupportedf("upgrade-series prepare")
   135  	}
   136  	args := params.UpdateSeriesArg{
   137  		Entity: params.Entity{
   138  			Tag: names.NewMachineTag(machineName).String()},
   139  		Series: series,
   140  		Force:  force,
   141  	}
   142  	result := params.ErrorResult{}
   143  	if err := client.facade.FacadeCall("UpgradeSeriesPrepare", args, &result); err != nil {
   144  		return errors.Trace(err)
   145  	}
   146  
   147  	err := result.Error
   148  	if err != nil {
   149  		return common.RestoreError(err)
   150  	}
   151  	return nil
   152  }
   153  
   154  // UpgradeSeriesComplete notifies the controller that a given machine has
   155  // successfully completed the managed series upgrade process.
   156  func (client *Client) UpgradeSeriesComplete(machineName string) error {
   157  	if client.BestAPIVersion() < 5 {
   158  		return errors.NotSupportedf("UpgradeSeriesComplete")
   159  	}
   160  	args := params.UpdateSeriesArg{
   161  		Entity: params.Entity{Tag: names.NewMachineTag(machineName).String()},
   162  	}
   163  	result := new(params.ErrorResult)
   164  	err := client.facade.FacadeCall("UpgradeSeriesComplete", args, result)
   165  	if err != nil {
   166  		return errors.Trace(err)
   167  	}
   168  	if result.Error != nil {
   169  		return result.Error
   170  	}
   171  
   172  	return nil
   173  }
   174  
   175  func (client *Client) UpgradeSeriesValidate(machineName, series string) ([]string, error) {
   176  	if client.BestAPIVersion() < 5 {
   177  		return nil, errors.NotSupportedf("UpgradeSeriesValidate")
   178  	}
   179  	args := params.UpdateSeriesArgs{
   180  		Args: []params.UpdateSeriesArg{
   181  			{
   182  				Entity: params.Entity{Tag: names.NewMachineTag(machineName).String()},
   183  				Series: series,
   184  			},
   185  		},
   186  	}
   187  	results := new(params.UpgradeSeriesUnitsResults)
   188  	err := client.facade.FacadeCall("UpgradeSeriesValidate", args, results)
   189  	if err != nil {
   190  		return nil, err
   191  	}
   192  	if n := len(results.Results); n != 1 {
   193  		return nil, errors.Errorf("expected 1 result, got %d", n)
   194  	}
   195  	if results.Results[0].Error != nil {
   196  		return nil, results.Results[0].Error
   197  	}
   198  	return results.Results[0].UnitNames, nil
   199  }
   200  
   201  // WatchUpgradeSeriesNotifications returns a NotifyWatcher for observing the state of
   202  // a series upgrade.
   203  func (client *Client) WatchUpgradeSeriesNotifications(machineName string) (watcher.NotifyWatcher, string, error) {
   204  	if client.BestAPIVersion() < 5 {
   205  		return nil, "", errors.NotSupportedf("WatchUpgradeSeriesNotifications")
   206  	}
   207  	var results params.NotifyWatchResults
   208  	args := params.Entities{
   209  		Entities: []params.Entity{{Tag: names.NewMachineTag(machineName).String()}},
   210  	}
   211  	err := client.facade.FacadeCall("WatchUpgradeSeriesNotifications", args, &results)
   212  	if err != nil {
   213  		return nil, "", errors.Trace(err)
   214  	}
   215  	if len(results.Results) != 1 {
   216  		return nil, "", errors.Errorf("expected 1 result, got %d", len(results.Results))
   217  	}
   218  	result := results.Results[0]
   219  	if result.Error != nil {
   220  		return nil, "", result.Error
   221  	}
   222  	w := apiwatcher.NewNotifyWatcher(client.facade.RawAPICaller(), result)
   223  	return w, result.NotifyWatcherId, nil
   224  }
   225  
   226  // GetUpgradeSeriesMessages returns a StringsWatcher for observing the state of
   227  // a series upgrade.
   228  func (client *Client) GetUpgradeSeriesMessages(machineName, watcherId string) ([]string, error) {
   229  	if client.BestAPIVersion() < 5 {
   230  		return nil, errors.NotSupportedf("GetUpgradeSeriesMessages")
   231  	}
   232  	var results params.StringsResults
   233  	args := params.UpgradeSeriesNotificationParams{
   234  		Params: []params.UpgradeSeriesNotificationParam{
   235  			{
   236  				Entity:    params.Entity{Tag: names.NewMachineTag(machineName).String()},
   237  				WatcherId: watcherId,
   238  			},
   239  		},
   240  	}
   241  	err := client.facade.FacadeCall("GetUpgradeSeriesMessages", args, &results)
   242  	if err != nil {
   243  		return nil, errors.Trace(err)
   244  	}
   245  	if len(results.Results) != 1 {
   246  		return nil, errors.Errorf("expected 1 result, got %d", len(results.Results))
   247  	}
   248  	result := results.Results[0]
   249  	if result.Error != nil {
   250  		return nil, result.Error
   251  	}
   252  
   253  	return result.Result, nil
   254  }