LEFT | RIGHT |
1 // Copyright 2012, 2013 Canonical Ltd. | 1 // Copyright 2012, 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package juju | 4 package juju |
5 | 5 |
6 import ( | 6 import ( |
7 "errors" | 7 "errors" |
8 "fmt" | 8 "fmt" |
9 "strings" | 9 "strings" |
10 | 10 |
11 "launchpad.net/juju-core/charm" | 11 "launchpad.net/juju-core/charm" |
12 "launchpad.net/juju-core/constraints" | 12 "launchpad.net/juju-core/constraints" |
13 "launchpad.net/juju-core/instance" | 13 "launchpad.net/juju-core/instance" |
14 "launchpad.net/juju-core/names" | 14 "launchpad.net/juju-core/names" |
15 "launchpad.net/juju-core/state" | 15 "launchpad.net/juju-core/state" |
16 ) | 16 ) |
17 | 17 |
18 // DeployServiceParams contains the arguments required to deploy the referenced | 18 // DeployServiceParams contains the arguments required to deploy the referenced |
19 // charm. | 19 // charm. |
20 type DeployServiceParams struct { | 20 type DeployServiceParams struct { |
21 ServiceName string | 21 ServiceName string |
22 Charm *state.Charm | 22 Charm *state.Charm |
23 ConfigSettings charm.Settings | 23 ConfigSettings charm.Settings |
24 Constraints constraints.Value | 24 Constraints constraints.Value |
25 NumUnits int | 25 NumUnits int |
26 // ToMachineSpec is either: | 26 // ToMachineSpec is either: |
27 // - an existing machine/container id eg "1" or "1/lxc/2" | 27 // - an existing machine/container id eg "1" or "1/lxc/2" |
28 // - a new container on an existing machine eg "lxc:1" | 28 // - a new container on an existing machine eg "lxc:1" |
29 // Use string to avoid ambiguity around machine 0. | 29 // Use string to avoid ambiguity around machine 0. |
30 » ToMachineSpec string | 30 » ToMachineSpec string |
31 » EnabledNetworks []string | 31 » // IncludeNetworks holds a list of networks to start on boot. |
32 » DisabledNetworks []string | 32 » IncludeNetworks []string |
| 33 » // ExcludeNetworks holds a list of networks to disable on boot. |
| 34 » ExcludeNetworks []string |
33 } | 35 } |
34 | 36 |
35 // DeployService takes a charm and various parameters and deploys it. | 37 // DeployService takes a charm and various parameters and deploys it. |
36 func DeployService(st *state.State, args DeployServiceParams) (*state.Service, e
rror) { | 38 func DeployService(st *state.State, args DeployServiceParams) (*state.Service, e
rror) { |
37 if args.NumUnits > 1 && args.ToMachineSpec != "" { | 39 if args.NumUnits > 1 && args.ToMachineSpec != "" { |
38 return nil, errors.New("cannot use --num-units with --to") | 40 return nil, errors.New("cannot use --num-units with --to") |
39 } | 41 } |
40 settings, err := args.Charm.Config().ValidateSettings(args.ConfigSetting
s) | 42 settings, err := args.Charm.Config().ValidateSettings(args.ConfigSetting
s) |
41 if err != nil { | 43 if err != nil { |
42 return nil, err | 44 return nil, err |
43 } | 45 } |
44 if args.Charm.Meta().Subordinate { | 46 if args.Charm.Meta().Subordinate { |
45 if args.NumUnits != 0 || args.ToMachineSpec != "" { | 47 if args.NumUnits != 0 || args.ToMachineSpec != "" { |
46 return nil, fmt.Errorf("subordinate service must be depl
oyed without units") | 48 return nil, fmt.Errorf("subordinate service must be depl
oyed without units") |
47 } | 49 } |
48 if !constraints.IsEmpty(&args.Constraints) { | 50 if !constraints.IsEmpty(&args.Constraints) { |
49 return nil, fmt.Errorf("subordinate service must be depl
oyed without constraints") | 51 return nil, fmt.Errorf("subordinate service must be depl
oyed without constraints") |
50 } | 52 } |
51 } | 53 } |
52 // TODO(fwereade): transactional State.AddService including settings, co
nstraints | 54 // TODO(fwereade): transactional State.AddService including settings, co
nstraints |
53 // (minimumUnitCount, initialMachineIds?). | 55 // (minimumUnitCount, initialMachineIds?). |
54 » service, err := st.AddService(args.ServiceName, "user-admin", args.Charm
) | 56 » service, err := st.AddService( |
| 57 » » args.ServiceName, |
| 58 » » "user-admin", |
| 59 » » args.Charm, |
| 60 » » args.IncludeNetworks, |
| 61 » » args.ExcludeNetworks, |
| 62 » ) |
55 if err != nil { | 63 if err != nil { |
56 return nil, err | 64 return nil, err |
57 } | 65 } |
58 if len(settings) > 0 { | 66 if len(settings) > 0 { |
59 if err := service.UpdateConfigSettings(settings); err != nil { | 67 if err := service.UpdateConfigSettings(settings); err != nil { |
60 return nil, err | 68 return nil, err |
61 } | 69 } |
62 } | 70 } |
63 if args.Charm.Meta().Subordinate { | 71 if args.Charm.Meta().Subordinate { |
64 return service, nil | 72 return service, nil |
65 } | 73 } |
66 if !constraints.IsEmpty(&args.Constraints) { | 74 if !constraints.IsEmpty(&args.Constraints) { |
67 if err := service.SetConstraints(args.Constraints); err != nil { | 75 if err := service.SetConstraints(args.Constraints); err != nil { |
68 return nil, err | 76 return nil, err |
69 } | 77 } |
70 } | 78 } |
71 if args.NumUnits > 0 { | 79 if args.NumUnits > 0 { |
72 if _, err := AddUnits(st, service, args.NumUnits, args.ToMachine
Spec); err != nil { | 80 if _, err := AddUnits(st, service, args.NumUnits, args.ToMachine
Spec); err != nil { |
73 return nil, err | 81 return nil, err |
74 } | 82 } |
75 } | 83 } |
76 // TODO(dimitern) Pass args.EnabledNetworks and | |
77 // args.DisabledNetworks down to the service document and/or | |
78 // MachineTemplate, once we have the networks in state. | |
79 return service, nil | 84 return service, nil |
80 } | 85 } |
81 | 86 |
82 // AddUnits starts n units of the given service and allocates machines | 87 // AddUnits starts n units of the given service and allocates machines |
83 // to them as necessary. | 88 // to them as necessary. |
84 func AddUnits(st *state.State, svc *state.Service, n int, machineIdSpec string)
([]*state.Unit, error) { | 89 func AddUnits(st *state.State, svc *state.Service, n int, machineIdSpec string)
([]*state.Unit, error) { |
85 units := make([]*state.Unit, n) | 90 units := make([]*state.Unit, n) |
86 // Hard code for now till we implement a different approach. | 91 // Hard code for now till we implement a different approach. |
87 policy := state.AssignCleanEmpty | 92 policy := state.AssignCleanEmpty |
| 93 // All units should have the same networks as the service. |
| 94 includeNetworks, excludeNetworks, err := svc.Networks() |
| 95 if err != nil { |
| 96 return nil, fmt.Errorf("cannot get service %q networks: %v", svc
.Name(), err) |
| 97 } |
88 // TODO what do we do if we fail half-way through this process? | 98 // TODO what do we do if we fail half-way through this process? |
89 for i := 0; i < n; i++ { | 99 for i := 0; i < n; i++ { |
90 unit, err := svc.AddUnit() | 100 unit, err := svc.AddUnit() |
91 if err != nil { | 101 if err != nil { |
92 return nil, fmt.Errorf("cannot add unit %d/%d to service
%q: %v", i+1, n, svc.Name(), err) | 102 return nil, fmt.Errorf("cannot add unit %d/%d to service
%q: %v", i+1, n, svc.Name(), err) |
93 } | 103 } |
94 if machineIdSpec != "" { | 104 if machineIdSpec != "" { |
95 if n != 1 { | 105 if n != 1 { |
96 return nil, fmt.Errorf("cannot add multiple unit
s of service %q to a single machine", svc.Name()) | 106 return nil, fmt.Errorf("cannot add multiple unit
s of service %q to a single machine", svc.Name()) |
97 } | 107 } |
(...skipping 15 matching lines...) Expand all Loading... |
113 return nil, fmt.Errorf("invalid force machine id
%q", mid) | 123 return nil, fmt.Errorf("invalid force machine id
%q", mid) |
114 } | 124 } |
115 | 125 |
116 var err error | 126 var err error |
117 var m *state.Machine | 127 var m *state.Machine |
118 // If a container is to be used, create it. | 128 // If a container is to be used, create it. |
119 if containerType != "" { | 129 if containerType != "" { |
120 // Create the new machine marked as dirty so tha
t | 130 // Create the new machine marked as dirty so tha
t |
121 // nothing else will grab it before we assign th
e unit to it. | 131 // nothing else will grab it before we assign th
e unit to it. |
122 template := state.MachineTemplate{ | 132 template := state.MachineTemplate{ |
123 » » » » » Series: unit.Series(), | 133 » » » » » Series: unit.Series(), |
124 » » » » » Jobs: []state.MachineJob{state.JobHost
Units}, | 134 » » » » » Jobs: []state.MachineJob{stat
e.JobHostUnits}, |
125 » » » » » Dirty: true, | 135 » » » » » Dirty: true, |
| 136 » » » » » IncludeNetworks: includeNetworks, |
| 137 » » » » » ExcludeNetworks: excludeNetworks, |
126 } | 138 } |
127 m, err = st.AddMachineInsideMachine(template, mi
d, containerType) | 139 m, err = st.AddMachineInsideMachine(template, mi
d, containerType) |
128 } else { | 140 } else { |
129 m, err = st.Machine(mid) | 141 m, err = st.Machine(mid) |
130 } | 142 } |
131 if err != nil { | 143 if err != nil { |
132 return nil, fmt.Errorf("cannot assign unit %q to
machine: %v", unit.Name(), err) | 144 return nil, fmt.Errorf("cannot assign unit %q to
machine: %v", unit.Name(), err) |
133 } | 145 } |
134 err = unit.AssignToMachine(m) | 146 err = unit.AssignToMachine(m) |
135 | 147 |
136 if err != nil { | 148 if err != nil { |
137 return nil, err | 149 return nil, err |
138 } | 150 } |
139 } else if err := st.AssignUnit(unit, policy); err != nil { | 151 } else if err := st.AssignUnit(unit, policy); err != nil { |
140 return nil, err | 152 return nil, err |
141 } | 153 } |
142 units[i] = unit | 154 units[i] = unit |
143 } | 155 } |
144 return units, nil | 156 return units, nil |
145 } | 157 } |
LEFT | RIGHT |