github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/apiserver/action/run.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package action 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/utils/set" 11 "gopkg.in/juju/names.v2" 12 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/core/actions" 15 "github.com/juju/juju/state" 16 ) 17 18 // getAllUnitNames returns a sequence of valid Unit objects from state. If any 19 // of the service names or unit names are not found, an error is returned. 20 func getAllUnitNames(st *state.State, units, services []string) (result []names.Tag, err error) { 21 unitsSet := set.NewStrings(units...) 22 for _, name := range services { 23 service, err := st.Application(name) 24 if err != nil { 25 return nil, err 26 } 27 units, err := service.AllUnits() 28 if err != nil { 29 return nil, err 30 } 31 for _, unit := range units { 32 unitsSet.Add(unit.Name()) 33 } 34 } 35 for _, unitName := range unitsSet.SortedValues() { 36 if !names.IsValidUnit(unitName) { 37 return nil, errors.Errorf("invalid unit name %q", unitName) 38 } 39 result = append(result, names.NewUnitTag(unitName)) 40 } 41 return result, nil 42 } 43 44 // Run the commands specified on the machines identified through the 45 // list of machines, units and services. 46 func (a *ActionAPI) Run(run params.RunParams) (results params.ActionResults, err error) { 47 if err := a.checkCanAdmin(); err != nil { 48 return results, err 49 } 50 if err := a.check.ChangeAllowed(); err != nil { 51 return results, errors.Trace(err) 52 } 53 54 units, err := getAllUnitNames(a.state, run.Units, run.Applications) 55 if err != nil { 56 return results, errors.Trace(err) 57 } 58 59 machines := make([]names.Tag, len(run.Machines)) 60 for i, machineId := range run.Machines { 61 if !names.IsValidMachine(machineId) { 62 return results, errors.Errorf("invalid machine id %q", machineId) 63 } 64 machines[i] = names.NewMachineTag(machineId) 65 } 66 67 actionParams := a.createActionsParams(append(units, machines...), run.Commands, run.Timeout) 68 69 return queueActions(a, actionParams) 70 } 71 72 // RunOnAllMachines attempts to run the specified command on all the machines. 73 func (a *ActionAPI) RunOnAllMachines(run params.RunParams) (results params.ActionResults, err error) { 74 if err := a.checkCanAdmin(); err != nil { 75 return results, err 76 } 77 78 if err := a.check.ChangeAllowed(); err != nil { 79 return results, errors.Trace(err) 80 } 81 82 machines, err := a.state.AllMachines() 83 if err != nil { 84 return results, err 85 } 86 machineTags := make([]names.Tag, len(machines)) 87 for i, machine := range machines { 88 machineTags[i] = machine.Tag() 89 } 90 91 actionParams := a.createActionsParams(machineTags, run.Commands, run.Timeout) 92 93 return queueActions(a, actionParams) 94 } 95 96 func (a *ActionAPI) createActionsParams(actionReceiverTags []names.Tag, quotedCommands string, timeout time.Duration) params.Actions { 97 98 apiActionParams := params.Actions{Actions: []params.Action{}} 99 100 actionParams := map[string]interface{}{} 101 actionParams["command"] = quotedCommands 102 actionParams["timeout"] = timeout.Nanoseconds() 103 104 for _, tag := range actionReceiverTags { 105 apiActionParams.Actions = append(apiActionParams.Actions, params.Action{ 106 Receiver: tag.String(), 107 Name: actions.JujuRunActionName, 108 Parameters: actionParams, 109 }) 110 } 111 112 return apiActionParams 113 } 114 115 var queueActions = func(a *ActionAPI, args params.Actions) (results params.ActionResults, err error) { 116 return a.Enqueue(args) 117 }