Merge lp:~gz/juju-core/openstack_network_config_1241674 into lp:~go-bot/juju-core/trunk
- openstack_network_config_1241674
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Martin Packman |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2255 |
Proposed branch: | lp:~gz/juju-core/openstack_network_config_1241674 |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
281 lines (+148/-9) 6 files modified
dependencies.tsv (+1/-1) provider/openstack/config.go (+6/-0) provider/openstack/config_test.go (+11/-0) provider/openstack/export_test.go (+5/-0) provider/openstack/local_test.go (+70/-0) provider/openstack/provider.go (+55/-8) |
To merge this branch: | bzr merge lp:~gz/juju-core/openstack_network_config_1241674 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+203114@code.launchpad.net |
Commit message
provider/openstack: Add network config option
Resolve issue with running juju on openstack setups with
multiple networks, by allowing the user to supply a
network label or id that juju should use for its machines.
https:/
R=natefinch
Description of the change
provider/openstack: Add network config option
Resolve issue with running juju on openstack setups with
multiple networks, by allowing the user to supply a
network label or id that juju should use for its machines.
Martin Packman (gz) wrote : | # |
William Reade (fwereade) wrote : | # |
quick comments -- thoughts?
https:/
File provider/
https:/
provider/
this feels like maybe it should be an Omit?
https:/
provider/
and this a `,ok`?
https:/
File provider/
https:/
provider/
"f81d4fae-
a thought: default-network? private-network?
https:/
provider/
"(?s)cannot run instance: .*itemNotFound.*")
I'd like to see a more precise error check here really.
Martin Packman (gz) wrote : | # |
Please take a look.
https:/
File provider/
https:/
provider/
"f81d4fae-
On 2014/01/24 16:53:49, fwereade wrote:
> a thought: default-network? private-network?
Yeah, config named 'network' is bad, but I think config for this at all
is bad. And it should take multiple values. I am resolved to leave some
bikeshedding for post 1.17.1 over this. :)
https:/
provider/
"(?s)cannot run instance: .*itemNotFound.*")
On 2014/01/24 16:53:49, fwereade wrote:
> I'd like to see a more precise error check here really.
Sadly our errors through goose are massively verbose, and the real
errors from (older at least) openstack versions are actually this
impresice. It might be an argument for doing more prechecking even when
a valid uuid is supplied.
Martin Packman (gz) wrote : | # |
Please take a look.
https:/
File provider/
https:/
provider/
"f81d4fae-
On 2014/01/24 16:53:49, fwereade wrote:
> a thought: default-network? private-network?
Yeah, config named 'network' is bad, but I think config for this at all
is bad. And it should take multiple values. I am resolved to leave some
bikeshedding for post 1.17.1 over this. :)
https:/
provider/
"(?s)cannot run instance: .*itemNotFound.*")
On 2014/01/24 16:53:49, fwereade wrote:
> I'd like to see a more precise error check here really.
Sadly our errors through goose are massively verbose, and the real
errors from (older at least) openstack versions are actually this
impresice. It might be an argument for doing more prechecking even when
a valid uuid is supplied.
Nate Finch (natefinch) wrote : | # |
LGTM with a couple small points.
https:/
File provider/
https:/
provider/
label or uuid to bring machines up on, in
s/networks/network
https:/
provider/
regexp.
Seems like there ought to be a function that verifies guids in Go
instead of hand-writing a regex...
Nate Finch (natefinch) wrote : | # |
LGTM with a couple small points.
https:/
File provider/
https:/
provider/
label or uuid to bring machines up on, in
s/networks/network
https:/
provider/
regexp.
Seems like there ought to be a function that verifies guids in Go
instead of hand-writing a regex...
Martin Packman (gz) wrote : | # |
Please take a look.
https:/
File provider/
https:/
provider/
label or uuid to bring machines up on, in
On 2014/01/24 20:12:45, nate.finch wrote:
> s/networks/network
Will fix... I did plan to allow supplying multiple initially, but we'll
leave that for later.
https:/
provider/
regexp.
On 2014/01/24 20:12:45, nate.finch wrote:
> Seems like there ought to be a function that verifies guids in Go
instead of
> hand-writing a regex...
Yes, yes there should. The best I could find was:
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~gz/juju-core/openstack_network_config_1241674 into lp:juju-core failed. Below is the output from the failed tests.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
-------
FAIL: machine_
[LOG] 83.93422 DEBUG juju.environs.
[LOG] 84.05088 DEBUG juju.environs.tools reading v1.* tools
[LOG] 84.05098 INFO juju environs/testing: uploading FAKE tools 1.17.1-
[LOG] 84.05221 DEBUG juju.environs.tools no architecture specified when finding tools, looking for any
[LOG] 84.05222 DEBUG juju.environs.tools no series specified when finding tools, looking for any
[LOG] 84.05233 DEBUG juju.environs.
[LOG] 84.05236 DEBUG juju.environs.
[LOG] 84.05240 DEBUG juju.environs.
[LOG] 84.05242 DEBUG juju.environs.
[LOG] 84.05287 INFO juju.environs.tools Writing tools/streams/
[LOG] 84.05294 INFO juju.environs.tools Writing tools/streams/
[LOG] 84.05313 INFO juju.environs.
[LOG] 84.05321 DEBUG juju.environs.
[LOG] 84.05324 INFO juju.environs.tools reading tools with major.minor version 1.17
[LOG] 84.05328 INFO juju.environs.tools filtering tools by version: 1.17.1
[LOG] 84.05328 INFO juju.environs.tools filtering tools by series: precise
[LOG] 84.05331 DEBUG juju.environs.tools no architecture specified when finding tools, looking for any
[LOG] 84.05333 DEBUG juju.environs.
[LOG] 84.05...
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~gz/juju-core/openstack_network_config_1241674 into lp:juju-core failed. Below is the output from the failed tests.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
-------
FAIL: machine_
[LOG] 51.17876 DEBUG juju.environs.
[LOG] 51.26292 DEBUG juju.environs.tools reading v1.* tools
[LOG] 51.26297 INFO juju environs/testing: uploading FAKE tools 1.17.1-
[LOG] 51.27510 DEBUG juju.environs.tools no architecture specified when finding tools, looking for any
[LOG] 51.27512 DEBUG juju.environs.tools no series specified when finding tools, looking for any
[LOG] 51.27519 DEBUG juju.environs.
[LOG] 51.27521 DEBUG juju.environs.
[LOG] 51.27525 DEBUG juju.environs.
[LOG] 51.27527 DEBUG juju.environs.
[LOG] 51.27555 INFO juju.environs.tools Writing tools/streams/
[LOG] 51.27564 INFO juju.environs.tools Writing tools/streams/
[LOG] 51.27579 INFO juju.environs.
[LOG] 51.27585 DEBUG juju.environs.
[LOG] 51.27586 INFO juju.environs.tools reading tools with major.minor version 1.17
[LOG] 51.27588 INFO juju.environs.tools filtering tools by version: 1.17.1
[LOG] 51.27588 INFO juju.environs.tools filtering tools by series: precise
[LOG] 51.27590 DEBUG juju.environs.tools no architecture specified when finding tools, looking for any
[LOG] 51.27594 DEBUG juju.environs.
Preview Diff
1 | === modified file 'dependencies.tsv' |
2 | --- dependencies.tsv 2014-01-22 01:37:16 +0000 |
3 | +++ dependencies.tsv 2014-01-24 20:43:20 +0000 |
4 | @@ -6,7 +6,7 @@ |
5 | launchpad.net/gocheck bzr gustavo@niemeyer.net-20130302024745-6ikofwq2c03h7giu 85 |
6 | launchpad.net/golxc bzr ian.booth@canonical.com-20140116225718-lvoikrb0me6zugin 6 |
7 | launchpad.net/gomaasapi bzr ian.booth@canonical.com-20131017011445-m1hmr0ap14osd7li 47 |
8 | -launchpad.net/goose bzr tarmac-20131223000240-y2igxjt3kznam7vi 114 |
9 | +launchpad.net/goose bzr tarmac-20140124165235-h9rloooc531udms5 116 |
10 | launchpad.net/goyaml bzr gustavo@niemeyer.net-20131114120802-abe042syx64z2m7s 50 |
11 | launchpad.net/gwacl bzr tarmac-20131031081035-b33m6fyrrdiuf408 229 |
12 | launchpad.net/loggo bzr tim.penhey@canonical.com-20130729043644-ym0cscir1cist4sm 39 |
13 | |
14 | === modified file 'provider/openstack/config.go' |
15 | --- provider/openstack/config.go 2013-12-23 00:46:18 +0000 |
16 | +++ provider/openstack/config.go 2014-01-24 20:43:20 +0000 |
17 | @@ -25,6 +25,7 @@ |
18 | "control-bucket": schema.String(), |
19 | "use-floating-ip": schema.Bool(), |
20 | "use-default-secgroup": schema.Bool(), |
21 | + "network": schema.String(), |
22 | } |
23 | var configDefaults = schema.Defaults{ |
24 | "username": "", |
25 | @@ -38,6 +39,7 @@ |
26 | "control-bucket": "", |
27 | "use-floating-ip": false, |
28 | "use-default-secgroup": false, |
29 | + "network": "", |
30 | } |
31 | |
32 | type environConfig struct { |
33 | @@ -89,6 +91,10 @@ |
34 | return c.attrs["use-default-secgroup"].(bool) |
35 | } |
36 | |
37 | +func (c *environConfig) network() string { |
38 | + return c.attrs["network"].(string) |
39 | +} |
40 | + |
41 | func (p environProvider) newConfig(cfg *config.Config) (*environConfig, error) { |
42 | valid, err := p.Validate(cfg, nil) |
43 | if err != nil { |
44 | |
45 | === modified file 'provider/openstack/config_test.go' |
46 | --- provider/openstack/config_test.go 2013-12-23 00:46:18 +0000 |
47 | +++ provider/openstack/config_test.go 2014-01-24 20:43:20 +0000 |
48 | @@ -58,6 +58,7 @@ |
49 | toolsURL string |
50 | useFloatingIP bool |
51 | useDefaultSecurityGroup bool |
52 | + network string |
53 | username string |
54 | password string |
55 | tenantName string |
56 | @@ -161,6 +162,7 @@ |
57 | } |
58 | c.Assert(ecfg.useFloatingIP(), gc.Equals, t.useFloatingIP) |
59 | c.Assert(ecfg.useDefaultSecurityGroup(), gc.Equals, t.useDefaultSecurityGroup) |
60 | + c.Assert(ecfg.network(), gc.Equals, t.network) |
61 | // Default should be true |
62 | expectedHostnameVerification := true |
63 | if t.sslHostnameSet { |
64 | @@ -430,6 +432,15 @@ |
65 | }, |
66 | sslHostnameVerification: true, |
67 | sslHostnameSet: true, |
68 | + }, { |
69 | + summary: "default network", |
70 | + network: "", |
71 | + }, { |
72 | + summary: "network", |
73 | + config: attrs{ |
74 | + "network": "a-network-label", |
75 | + }, |
76 | + network: "a-network-label", |
77 | }, |
78 | } |
79 | |
80 | |
81 | === modified file 'provider/openstack/export_test.go' |
82 | --- provider/openstack/export_test.go 2013-12-10 04:25:06 +0000 |
83 | +++ provider/openstack/export_test.go 2014-01-24 20:43:20 +0000 |
84 | @@ -311,3 +311,8 @@ |
85 | func GetNovaClient(e environs.Environ) *nova.Client { |
86 | return e.(*environ).nova() |
87 | } |
88 | + |
89 | +// ResolveNetwork exposes environ helper function resolveNetwork for testing |
90 | +func ResolveNetwork(e environs.Environ, networkName string) (string, error) { |
91 | + return e.(*environ).resolveNetwork(networkName) |
92 | +} |
93 | |
94 | === modified file 'provider/openstack/local_test.go' |
95 | --- provider/openstack/local_test.go 2013-12-20 02:38:56 +0000 |
96 | +++ provider/openstack/local_test.go 2014-01-24 20:43:20 +0000 |
97 | @@ -332,6 +332,48 @@ |
98 | c.Assert(hc.CpuPower, gc.IsNil) |
99 | } |
100 | |
101 | +func (s *localServerSuite) TestStartInstanceNetwork(c *gc.C) { |
102 | + cfg, err := config.New(config.NoDefaults, s.TestConfig.Merge(coretesting.Attrs{ |
103 | + // A label that corresponds to a nova test service network |
104 | + "network": "net", |
105 | + })) |
106 | + c.Assert(err, gc.IsNil) |
107 | + env, err := environs.New(cfg) |
108 | + c.Assert(err, gc.IsNil) |
109 | + inst, _ := testing.AssertStartInstance(c, env, "100") |
110 | + err = env.StopInstances([]instance.Instance{inst}) |
111 | + c.Assert(err, gc.IsNil) |
112 | +} |
113 | + |
114 | +func (s *localServerSuite) TestStartInstanceNetworkUnknownLabel(c *gc.C) { |
115 | + cfg, err := config.New(config.NoDefaults, s.TestConfig.Merge(coretesting.Attrs{ |
116 | + // A label that has no related network in the nova test service |
117 | + "network": "no-network-with-this-label", |
118 | + })) |
119 | + c.Assert(err, gc.IsNil) |
120 | + env, err := environs.New(cfg) |
121 | + c.Assert(err, gc.IsNil) |
122 | + inst, _, err := testing.StartInstance(env, "100") |
123 | + c.Check(inst, gc.IsNil) |
124 | + c.Assert(err, gc.ErrorMatches, "No networks exist with label .*") |
125 | +} |
126 | + |
127 | +func (s *localServerSuite) TestStartInstanceNetworkUnknownId(c *gc.C) { |
128 | + cfg, err := config.New(config.NoDefaults, s.TestConfig.Merge(coretesting.Attrs{ |
129 | + // A valid UUID but no related network in the nova test service |
130 | + "network": "f81d4fae-7dec-11d0-a765-00a0c91e6bf6", |
131 | + })) |
132 | + c.Assert(err, gc.IsNil) |
133 | + env, err := environs.New(cfg) |
134 | + c.Assert(err, gc.IsNil) |
135 | + inst, _, err := testing.StartInstance(env, "100") |
136 | + c.Check(inst, gc.IsNil) |
137 | + c.Assert(err, gc.ErrorMatches, "cannot run instance: (\\n|.)*"+ |
138 | + "caused by: "+ |
139 | + "request \\(.*/servers\\) returned unexpected status: "+ |
140 | + "404; error info: .*itemNotFound.*") |
141 | +} |
142 | + |
143 | var instanceGathering = []struct { |
144 | ids []instance.Id |
145 | err error |
146 | @@ -939,3 +981,31 @@ |
147 | c.Assert(err, gc.IsNil) |
148 | c.Check(insts, gc.HasLen, 1) |
149 | } |
150 | + |
151 | +func (s *localServerSuite) TestResolveNetworkUUID(c *gc.C) { |
152 | + env := s.Prepare(c) |
153 | + var sampleUUID = "f81d4fae-7dec-11d0-a765-00a0c91e6bf6" |
154 | + networkId, err := openstack.ResolveNetwork(env, sampleUUID) |
155 | + c.Assert(err, gc.IsNil) |
156 | + c.Assert(networkId, gc.Equals, sampleUUID) |
157 | +} |
158 | + |
159 | +func (s *localServerSuite) TestResolveNetworkLabel(c *gc.C) { |
160 | + env := s.Prepare(c) |
161 | + // For now this test has to cheat and use knowledge of goose internals |
162 | + var networkLabel = "net" |
163 | + var expectNetworkId = "1" |
164 | + networkId, err := openstack.ResolveNetwork(env, networkLabel) |
165 | + c.Assert(err, gc.IsNil) |
166 | + c.Assert(networkId, gc.Equals, expectNetworkId) |
167 | +} |
168 | + |
169 | +func (s *localServerSuite) TestResolveNetworkNotPresent(c *gc.C) { |
170 | + env := s.Prepare(c) |
171 | + var notPresentNetwork = "no-network-with-this-label" |
172 | + networkId, err := openstack.ResolveNetwork(env, notPresentNetwork) |
173 | + c.Check(networkId, gc.Equals, "") |
174 | + c.Assert(err, gc.ErrorMatches, `No networks exist with label "no-network-with-this-label"`) |
175 | +} |
176 | + |
177 | +// TODO(gz): TestResolveNetworkMultipleMatching when can inject new networks |
178 | |
179 | === modified file 'provider/openstack/provider.go' |
180 | --- provider/openstack/provider.go 2014-01-20 17:18:13 +0000 |
181 | +++ provider/openstack/provider.go 2014-01-24 20:43:20 +0000 |
182 | @@ -10,6 +10,7 @@ |
183 | "fmt" |
184 | "io/ioutil" |
185 | "net/http" |
186 | + "regexp" |
187 | "strings" |
188 | "sync" |
189 | "time" |
190 | @@ -75,6 +76,10 @@ |
191 | # Openstack security group assigned. |
192 | # use-default-secgroup: false |
193 | |
194 | + # network specifies the network label or uuid to bring machines up on, in |
195 | + # the case where multiple networks exist. It may be omitted otherwise. |
196 | + # network: <your network label or uuid> |
197 | + |
198 | # tools-metadata-url specifies the location of the Juju tools and metadata. It defaults to the |
199 | # global public tools metadata location https://streams.canonical.com/tools. |
200 | # tools-metadata-url: https://you-tools-metadata-url |
201 | @@ -631,6 +636,37 @@ |
202 | return e.toolsSources, nil |
203 | } |
204 | |
205 | +// TODO(gz): Move this somewhere more reusable |
206 | +const uuidPattern = "^([a-fA-F0-9]{8})-([a-fA-f0-9]{4})-([1-5][a-fA-f0-9]{3})-([a-fA-f0-9]{4})-([a-fA-f0-9]{12})$" |
207 | + |
208 | +var uuidRegexp = regexp.MustCompile(uuidPattern) |
209 | + |
210 | +// resolveNetwork takes either a network id or label and returns a network id |
211 | +func (e *environ) resolveNetwork(networkName string) (string, error) { |
212 | + if uuidRegexp.MatchString(networkName) { |
213 | + // Network id supplied, assume valid as boot will fail if not |
214 | + return networkName, nil |
215 | + } |
216 | + // Network label supplied, resolve to a network id |
217 | + networks, err := e.nova().ListNetworks() |
218 | + if err != nil { |
219 | + return "", err |
220 | + } |
221 | + var networkIds = []string{} |
222 | + for _, network := range networks { |
223 | + if network.Label == networkName { |
224 | + networkIds = append(networkIds, network.Id) |
225 | + } |
226 | + } |
227 | + switch len(networkIds) { |
228 | + case 1: |
229 | + return networkIds[0], nil |
230 | + case 0: |
231 | + return "", fmt.Errorf("No networks exist with label %q", networkName) |
232 | + } |
233 | + return "", fmt.Errorf("Multiple networks with label %q: %v", networkName, networkIds) |
234 | +} |
235 | + |
236 | // allocatePublicIP tries to find an available floating IP address, or |
237 | // allocates a new one, returning it, or an error |
238 | func (e *environ) allocatePublicIP() (*nova.FloatingIP, error) { |
239 | @@ -711,6 +747,16 @@ |
240 | return nil, nil, fmt.Errorf("cannot make user data: %v", err) |
241 | } |
242 | logger.Debugf("openstack user data; %d bytes", len(userData)) |
243 | + var networks = []nova.ServerNetworks{} |
244 | + usingNetwork := e.ecfg().network() |
245 | + if usingNetwork != "" { |
246 | + networkId, err := e.resolveNetwork(usingNetwork) |
247 | + if err != nil { |
248 | + return nil, nil, err |
249 | + } |
250 | + logger.Debugf("using network id %q", networkId) |
251 | + networks = append(networks, nova.ServerNetworks{NetworkId: networkId}) |
252 | + } |
253 | withPublicIP := e.ecfg().useFloatingIP() |
254 | var publicIP *nova.FloatingIP |
255 | if withPublicIP { |
256 | @@ -730,16 +776,17 @@ |
257 | for i, g := range groups { |
258 | groupNames[i] = nova.SecurityGroupName{g.Name} |
259 | } |
260 | - |
261 | + var opts = nova.RunServerOpts{ |
262 | + Name: e.machineFullName(machineConfig.MachineId), |
263 | + FlavorId: spec.InstanceType.Id, |
264 | + ImageId: spec.Image.Id, |
265 | + UserData: userData, |
266 | + SecurityGroupNames: groupNames, |
267 | + Networks: networks, |
268 | + } |
269 | var server *nova.Entity |
270 | for a := shortAttempt.Start(); a.Next(); { |
271 | - server, err = e.nova().RunServer(nova.RunServerOpts{ |
272 | - Name: e.machineFullName(machineConfig.MachineId), |
273 | - FlavorId: spec.InstanceType.Id, |
274 | - ImageId: spec.Image.Id, |
275 | - UserData: userData, |
276 | - SecurityGroupNames: groupNames, |
277 | - }) |
278 | + server, err = e.nova().RunServer(opts) |
279 | if err == nil || !gooseerrors.IsNotFound(err) { |
280 | break |
281 | } |
Reviewers: mp+203114_ code.launchpad. net,
Message:
Please take a look.
Description:
provider/openstack: Add network config option
Resolve issue with running juju on openstack setups with
multiple networks, by allowing the user to supply a
network label or id that juju should use for its machines.
Note: this still requires a dependencies.tsv goose bump
https:/ /code.launchpad .net/~gz/ juju-core/ openstack_ network_ config_ 1241674/ +merge/ 203114
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/52710048/
Affected files (+146, -8 lines): openstack/ config. go openstack/ config_ test.go openstack/ export_ test.go openstack/ local_test. go openstack/ provider. go
A [revision details]
M provider/
M provider/
M provider/
M provider/
M provider/