Merge lp:~tr3buchet/nova/xs_network_inject into lp:~hudson-openstack/nova/trunk
- xs_network_inject
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Matt Dietz |
Approved revision: | 612 |
Merged at revision: | 690 |
Proposed branch: | lp:~tr3buchet/nova/xs_network_inject |
Merge into: | lp:~hudson-openstack/nova/trunk |
Diff against target: |
480 lines (+223/-13) 15 files modified
bin/nova-manage (+5/-4) nova/api/openstack/__init__.py (+1/-0) nova/api/openstack/servers.py (+14/-0) nova/compute/api.py (+7/-0) nova/compute/manager.py (+12/-0) nova/db/api.py (+10/-0) nova/db/sqlalchemy/api.py (+24/-0) nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py (+51/-0) nova/db/sqlalchemy/models.py (+1/-0) nova/network/manager.py (+7/-1) nova/tests/api/openstack/test_servers.py (+12/-0) nova/tests/test_xenapi.py (+6/-0) nova/virt/xenapi/vmops.py (+55/-7) nova/virt/xenapi_conn.py (+4/-0) plugins/xenserver/xenapi/etc/xapi.d/plugins/agent (+14/-1) |
To merge this branch: | bzr merge lp:~tr3buchet/nova/xs_network_inject |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ed Leafe (community) | Approve | ||
Sandy Walsh (community) | Approve | ||
Jay Pipes (community) | Approve | ||
Matt Dietz (community) | Approve | ||
Review via email: mp+49906@code.launchpad.net |
Commit message
Description of the change
added labels to networks for use in multi-nic
added writing network data to xenstore param-list
added call to agent to reset network
added reset_network call to openstack api
Trey Morris (tr3buchet) wrote : | # |
wow, for the life of me i can't figure out how that tabstop got set to 5.. must have been some rogue vim keystrokes or something
Jay Pipes (jaypipes) wrote : | # |
Per our conversation on IRC, I now see you supplying the label='public' to the create_networks() function in nova-manage. You can disregard that comment from my review. Thanks!
Trey Morris (tr3buchet) wrote : | # |
updates in place.
Ed Leafe (ed-leafe) wrote : | # |
The new file "nova/db/
# Copyright 2011 OpenStack LLC
Other than that, lgtm.
Sandy Walsh (sandy-walsh) wrote : | # |
Good job Trey!
Why does network_
Not your fault, but too bad we can't get any unit tests at the Xen level ... where it's needed.
Trivial comment: doc strings should be proper sentences (caps and punctuation) and remove unnecessary whitespace. (compute.api)
I'll approve after I hear back from you.
Trey Morris (tr3buchet) wrote : | # |
dabo: easy peasy
sandy: FixedIPs as opposed to both fixed and floating? caps and punctuation :(. englilish is getting into the code it seems
Trey Morris (tr3buchet) wrote : | # |
still checking fixed IPs only as no one knows what floating IPs are. Also haven't heard back from anyone who should.
Preview Diff
1 | === modified file 'bin/nova-manage' |
2 | --- bin/nova-manage 2011-02-17 17:59:51 +0000 |
3 | +++ bin/nova-manage 2011-02-17 19:12:16 +0000 |
4 | @@ -472,8 +472,8 @@ |
5 | """Class for managing networks.""" |
6 | |
7 | def create(self, fixed_range=None, num_networks=None, |
8 | - network_size=None, vlan_start=None, vpn_start=None, |
9 | - fixed_range_v6=None): |
10 | + network_size=None, vlan_start=None, |
11 | + vpn_start=None, fixed_range_v6=None, label='public'): |
12 | """Creates fixed ips for host by range |
13 | arguments: [fixed_range=FLAG], [num_networks=FLAG], |
14 | [network_size=FLAG], [vlan_start=FLAG], |
15 | @@ -495,9 +495,10 @@ |
16 | cidr=fixed_range, |
17 | num_networks=int(num_networks), |
18 | network_size=int(network_size), |
19 | + vlan_start=int(vlan_start), |
20 | + vpn_start=int(vpn_start), |
21 | cidr_v6=fixed_range_v6, |
22 | - vlan_start=int(vlan_start), |
23 | - vpn_start=int(vpn_start)) |
24 | + label=label) |
25 | |
26 | def list(self): |
27 | """List all created networks""" |
28 | |
29 | === modified file 'nova/api/openstack/__init__.py' |
30 | --- nova/api/openstack/__init__.py 2011-01-31 22:43:03 +0000 |
31 | +++ nova/api/openstack/__init__.py 2011-02-17 19:12:16 +0000 |
32 | @@ -79,6 +79,7 @@ |
33 | server_members["actions"] = "GET" |
34 | server_members['suspend'] = 'POST' |
35 | server_members['resume'] = 'POST' |
36 | + server_members['reset_network'] = 'POST' |
37 | |
38 | mapper.resource("server", "servers", controller=servers.Controller(), |
39 | collection={'detail': 'GET'}, |
40 | |
41 | === modified file 'nova/api/openstack/servers.py' |
42 | --- nova/api/openstack/servers.py 2011-01-26 16:16:16 +0000 |
43 | +++ nova/api/openstack/servers.py 2011-02-17 19:12:16 +0000 |
44 | @@ -249,6 +249,20 @@ |
45 | return faults.Fault(exc.HTTPUnprocessableEntity()) |
46 | return exc.HTTPAccepted() |
47 | |
48 | + def reset_network(self, req, id): |
49 | + """ |
50 | + Reset networking on an instance (admin only). |
51 | + |
52 | + """ |
53 | + context = req.environ['nova.context'] |
54 | + try: |
55 | + self.compute_api.reset_network(context, id) |
56 | + except: |
57 | + readable = traceback.format_exc() |
58 | + LOG.exception(_("Compute.api::reset_network %s"), readable) |
59 | + return faults.Fault(exc.HTTPUnprocessableEntity()) |
60 | + return exc.HTTPAccepted() |
61 | + |
62 | def pause(self, req, id): |
63 | """ Permit Admins to Pause the server. """ |
64 | ctxt = req.environ['nova.context'] |
65 | |
66 | === modified file 'nova/compute/api.py' |
67 | --- nova/compute/api.py 2011-02-15 18:19:52 +0000 |
68 | +++ nova/compute/api.py 2011-02-17 19:12:16 +0000 |
69 | @@ -466,6 +466,13 @@ |
70 | instance = self.get(context, instance_id) |
71 | return instance['locked'] |
72 | |
73 | + def reset_network(self, context, instance_id): |
74 | + """ |
75 | + Reset networking on the instance. |
76 | + |
77 | + """ |
78 | + self._cast_compute_message('reset_network', context, instance_id) |
79 | + |
80 | def attach_volume(self, context, instance_id, volume_id, device): |
81 | if not re.match("^/dev/[a-z]d[a-z]+$", device): |
82 | raise exception.ApiError(_("Invalid device specified: %s. " |
83 | |
84 | === modified file 'nova/compute/manager.py' |
85 | --- nova/compute/manager.py 2011-02-09 10:08:15 +0000 |
86 | +++ nova/compute/manager.py 2011-02-17 19:12:16 +0000 |
87 | @@ -498,6 +498,18 @@ |
88 | instance_ref = self.db.instance_get(context, instance_id) |
89 | return instance_ref['locked'] |
90 | |
91 | + @checks_instance_lock |
92 | + def reset_network(self, context, instance_id): |
93 | + """ |
94 | + Reset networking on the instance. |
95 | + |
96 | + """ |
97 | + context = context.elevated() |
98 | + instance_ref = self.db.instance_get(context, instance_id) |
99 | + LOG.debug(_('instance %s: reset network'), instance_id, |
100 | + context=context) |
101 | + self.driver.reset_network(instance_ref) |
102 | + |
103 | @exception.wrap_exception |
104 | def get_console_output(self, context, instance_id): |
105 | """Send the console output for an instance.""" |
106 | |
107 | === modified file 'nova/db/api.py' |
108 | --- nova/db/api.py 2011-02-16 11:15:48 +0000 |
109 | +++ nova/db/api.py 2011-02-17 19:12:16 +0000 |
110 | @@ -293,6 +293,11 @@ |
111 | return IMPL.fixed_ip_get_by_address(context, address) |
112 | |
113 | |
114 | +def fixed_ip_get_all_by_instance(context, instance_id): |
115 | + """Get fixed ips by instance or raise if none exist.""" |
116 | + return IMPL.fixed_ip_get_all_by_instance(context, instance_id) |
117 | + |
118 | + |
119 | def fixed_ip_get_instance(context, address): |
120 | """Get an instance for a fixed ip by address.""" |
121 | return IMPL.fixed_ip_get_instance(context, address) |
122 | @@ -521,6 +526,11 @@ |
123 | return IMPL.network_get_by_instance(context, instance_id) |
124 | |
125 | |
126 | +def network_get_all_by_instance(context, instance_id): |
127 | + """Get all networks by instance id or raise if none exist.""" |
128 | + return IMPL.network_get_all_by_instance(context, instance_id) |
129 | + |
130 | + |
131 | def network_get_index(context, network_id): |
132 | """Get non-conflicting index for network.""" |
133 | return IMPL.network_get_index(context, network_id) |
134 | |
135 | === modified file 'nova/db/sqlalchemy/api.py' |
136 | --- nova/db/sqlalchemy/api.py 2011-02-17 14:14:45 +0000 |
137 | +++ nova/db/sqlalchemy/api.py 2011-02-17 19:12:16 +0000 |
138 | @@ -609,6 +609,17 @@ |
139 | |
140 | |
141 | @require_context |
142 | +def fixed_ip_get_all_by_instance(context, instance_id): |
143 | + session = get_session() |
144 | + rv = session.query(models.FixedIp).\ |
145 | + filter_by(instance_id=instance_id).\ |
146 | + filter_by(deleted=False) |
147 | + if not rv: |
148 | + raise exception.NotFound(_('No address for instance %s') % instance_id) |
149 | + return rv |
150 | + |
151 | + |
152 | +@require_context |
153 | def fixed_ip_get_instance_v6(context, address): |
154 | session = get_session() |
155 | mac = utils.to_mac(address) |
156 | @@ -1109,6 +1120,19 @@ |
157 | |
158 | |
159 | @require_admin_context |
160 | +def network_get_all_by_instance(_context, instance_id): |
161 | + session = get_session() |
162 | + rv = session.query(models.Network).\ |
163 | + filter_by(deleted=False).\ |
164 | + join(models.Network.fixed_ips).\ |
165 | + filter_by(instance_id=instance_id).\ |
166 | + filter_by(deleted=False) |
167 | + if not rv: |
168 | + raise exception.NotFound(_('No network for instance %s') % instance_id) |
169 | + return rv |
170 | + |
171 | + |
172 | +@require_admin_context |
173 | def network_set_host(context, network_id, host_id): |
174 | session = get_session() |
175 | with session.begin(): |
176 | |
177 | === added file 'nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py' |
178 | --- nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py 1970-01-01 00:00:00 +0000 |
179 | +++ nova/db/sqlalchemy/migrate_repo/versions/003_add_label_to_networks.py 2011-02-17 19:12:16 +0000 |
180 | @@ -0,0 +1,51 @@ |
181 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
182 | + |
183 | +# Copyright 2011 OpenStack LLC |
184 | +# All Rights Reserved. |
185 | +# |
186 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
187 | +# not use this file except in compliance with the License. You may obtain |
188 | +# a copy of the License at |
189 | +# |
190 | +# http://www.apache.org/licenses/LICENSE-2.0 |
191 | +# |
192 | +# Unless required by applicable law or agreed to in writing, software |
193 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
194 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
195 | +# License for the specific language governing permissions and limitations |
196 | +# under the License. |
197 | + |
198 | +from sqlalchemy import * |
199 | +from migrate import * |
200 | + |
201 | +from nova import log as logging |
202 | + |
203 | + |
204 | +meta = MetaData() |
205 | + |
206 | + |
207 | +networks = Table('networks', meta, |
208 | + Column('id', Integer(), primary_key=True, nullable=False), |
209 | + ) |
210 | + |
211 | + |
212 | +# |
213 | +# New Tables |
214 | +# |
215 | + |
216 | + |
217 | +# |
218 | +# Tables to alter |
219 | +# |
220 | + |
221 | +networks_label = Column( |
222 | + 'label', |
223 | + String(length=255, convert_unicode=False, assert_unicode=None, |
224 | + unicode_error=None, _warn_on_bytestring=False)) |
225 | + |
226 | + |
227 | +def upgrade(migrate_engine): |
228 | + # Upgrade operations go here. Don't create your own engine; |
229 | + # bind migrate_engine to your metadata |
230 | + meta.bind = migrate_engine |
231 | + networks.create_column(networks_label) |
232 | |
233 | === modified file 'nova/db/sqlalchemy/models.py' |
234 | --- nova/db/sqlalchemy/models.py 2011-02-01 16:09:34 +0000 |
235 | +++ nova/db/sqlalchemy/models.py 2011-02-17 19:12:16 +0000 |
236 | @@ -373,6 +373,7 @@ |
237 | "vpn_public_port"), |
238 | {'mysql_engine': 'InnoDB'}) |
239 | id = Column(Integer, primary_key=True) |
240 | + label = Column(String(255)) |
241 | |
242 | injected = Column(Boolean, default=False) |
243 | cidr = Column(String(255), unique=True) |
244 | |
245 | === modified file 'nova/network/manager.py' |
246 | --- nova/network/manager.py 2011-02-09 20:49:25 +0000 |
247 | +++ nova/network/manager.py 2011-02-17 19:12:16 +0000 |
248 | @@ -331,11 +331,12 @@ |
249 | pass |
250 | |
251 | def create_networks(self, context, cidr, num_networks, network_size, |
252 | - cidr_v6, *args, **kwargs): |
253 | + cidr_v6, label, *args, **kwargs): |
254 | """Create networks based on parameters.""" |
255 | fixed_net = IPy.IP(cidr) |
256 | fixed_net_v6 = IPy.IP(cidr_v6) |
257 | significant_bits_v6 = 64 |
258 | + count = 1 |
259 | for index in range(num_networks): |
260 | start = index * network_size |
261 | significant_bits = 32 - int(math.log(network_size, 2)) |
262 | @@ -348,6 +349,11 @@ |
263 | net['gateway'] = str(project_net[1]) |
264 | net['broadcast'] = str(project_net.broadcast()) |
265 | net['dhcp_start'] = str(project_net[2]) |
266 | + if num_networks > 1: |
267 | + net['label'] = "%s_%d" % (label, count) |
268 | + else: |
269 | + net['label'] = label |
270 | + count += 1 |
271 | |
272 | if(FLAGS.use_ipv6): |
273 | cidr_v6 = "%s/%s" % (fixed_net_v6[0], significant_bits_v6) |
274 | |
275 | === modified file 'nova/tests/api/openstack/test_servers.py' |
276 | --- nova/tests/api/openstack/test_servers.py 2011-01-27 18:48:00 +0000 |
277 | +++ nova/tests/api/openstack/test_servers.py 2011-02-17 19:12:16 +0000 |
278 | @@ -281,6 +281,18 @@ |
279 | res = req.get_response(fakes.wsgi_app()) |
280 | self.assertEqual(res.status_int, 202) |
281 | |
282 | + def test_server_reset_network(self): |
283 | + FLAGS.allow_admin_api = True |
284 | + body = dict(server=dict( |
285 | + name='server_test', imageId=2, flavorId=2, metadata={}, |
286 | + personality={})) |
287 | + req = webob.Request.blank('/v1.0/servers/1/reset_network') |
288 | + req.method = 'POST' |
289 | + req.content_type = 'application/json' |
290 | + req.body = json.dumps(body) |
291 | + res = req.get_response(fakes.wsgi_app()) |
292 | + self.assertEqual(res.status_int, 202) |
293 | + |
294 | def test_server_diagnostics(self): |
295 | req = webob.Request.blank("/v1.0/servers/1/diagnostics") |
296 | req.method = "GET" |
297 | |
298 | === modified file 'nova/tests/test_xenapi.py' |
299 | --- nova/tests/test_xenapi.py 2011-02-09 10:08:15 +0000 |
300 | +++ nova/tests/test_xenapi.py 2011-02-17 19:12:16 +0000 |
301 | @@ -32,6 +32,7 @@ |
302 | from nova.virt.xenapi import fake as xenapi_fake |
303 | from nova.virt.xenapi import volume_utils |
304 | from nova.virt.xenapi.vmops import SimpleDH |
305 | +from nova.virt.xenapi.vmops import VMOps |
306 | from nova.tests.db import fakes as db_fakes |
307 | from nova.tests.xenapi import stubs |
308 | from nova.tests.glance import stubs as glance_stubs |
309 | @@ -141,6 +142,10 @@ |
310 | self.stubs.UnsetAll() |
311 | |
312 | |
313 | +def reset_network(*args): |
314 | + pass |
315 | + |
316 | + |
317 | class XenAPIVMTestCase(test.TestCase): |
318 | """ |
319 | Unit tests for VM operations |
320 | @@ -162,6 +167,7 @@ |
321 | stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) |
322 | stubs.stubout_get_this_vm_uuid(self.stubs) |
323 | stubs.stubout_stream_disk(self.stubs) |
324 | + self.stubs.Set(VMOps, 'reset_network', reset_network) |
325 | glance_stubs.stubout_glance_client(self.stubs, |
326 | glance_stubs.FakeGlance) |
327 | self.conn = xenapi_conn.get_connection(False) |
328 | |
329 | === modified file 'nova/virt/xenapi/vmops.py' |
330 | --- nova/virt/xenapi/vmops.py 2011-02-15 17:30:19 +0000 |
331 | +++ nova/virt/xenapi/vmops.py 2011-02-17 19:12:16 +0000 |
332 | @@ -66,6 +66,7 @@ |
333 | if vm is not None: |
334 | raise exception.Duplicate(_('Attempted to create' |
335 | ' non-unique name %s') % instance.name) |
336 | + |
337 | #ensure enough free memory is available |
338 | if not VMHelper.ensure_free_mem(self._session, instance): |
339 | name = instance['name'] |
340 | @@ -75,10 +76,6 @@ |
341 | instance['id'], |
342 | power_state.SHUTDOWN) |
343 | return |
344 | - bridge = db.network_get_by_instance(context.get_admin_context(), |
345 | - instance['id'])['bridge'] |
346 | - network_ref = \ |
347 | - NetworkHelper.find_network_with_bridge(self._session, bridge) |
348 | |
349 | user = AuthManager().get_user(instance.user_id) |
350 | project = AuthManager().get_project(instance.project_id) |
351 | @@ -107,9 +104,46 @@ |
352 | instance, kernel, ramdisk, pv_kernel) |
353 | VMHelper.create_vbd(self._session, vm_ref, vdi_ref, 0, True) |
354 | |
355 | - if network_ref: |
356 | - VMHelper.create_vif(self._session, vm_ref, |
357 | - network_ref, instance.mac_address) |
358 | + # write network info |
359 | + admin_context = context.get_admin_context() |
360 | + |
361 | + # TODO(tr3buchet) - remove comment in multi-nic |
362 | + # I've decided to go ahead and consider multiple IPs and networks |
363 | + # at this stage even though they aren't implemented because these will |
364 | + # be needed for multi-nic and there was no sense writing it for single |
365 | + # network/single IP and then having to turn around and re-write it |
366 | + IPs = db.fixed_ip_get_all_by_instance(admin_context, instance['id']) |
367 | + for network in db.network_get_all_by_instance(admin_context, |
368 | + instance['id']): |
369 | + network_IPs = [ip for ip in IPs if ip.network_id == network.id] |
370 | + |
371 | + def ip_dict(ip): |
372 | + return {'netmask': network['netmask'], |
373 | + 'enabled': '1', |
374 | + 'ip': ip.address} |
375 | + |
376 | + mac_id = instance.mac_address.replace(':', '') |
377 | + location = 'vm-data/networking/%s' % mac_id |
378 | + mapping = {'label': network['label'], |
379 | + 'gateway': network['gateway'], |
380 | + 'mac': instance.mac_address, |
381 | + 'dns': [network['dns']], |
382 | + 'ips': [ip_dict(ip) for ip in network_IPs]} |
383 | + self.write_to_param_xenstore(vm_ref, {location: mapping}) |
384 | + |
385 | + # TODO(tr3buchet) - remove comment in multi-nic |
386 | + # this bit here about creating the vifs will be updated |
387 | + # in multi-nic to handle multiple IPs on the same network |
388 | + # and multiple networks |
389 | + # for now it works as there is only one of each |
390 | + bridge = network['bridge'] |
391 | + network_ref = \ |
392 | + NetworkHelper.find_network_with_bridge(self._session, bridge) |
393 | + |
394 | + if network_ref: |
395 | + VMHelper.create_vif(self._session, vm_ref, |
396 | + network_ref, instance.mac_address) |
397 | + |
398 | LOG.debug(_('Starting VM %s...'), vm_ref) |
399 | self._session.call_xenapi('VM.start', vm_ref, False, False) |
400 | instance_name = instance.name |
401 | @@ -117,6 +151,8 @@ |
402 | % locals()) |
403 | |
404 | # NOTE(armando): Do we really need to do this in virt? |
405 | + # NOTE(tr3buchet): not sure but wherever we do it, we need to call |
406 | + # reset_network afterwards |
407 | timer = utils.LoopingCall(f=None) |
408 | |
409 | def _wait_for_boot(): |
410 | @@ -137,6 +173,10 @@ |
411 | timer.stop() |
412 | |
413 | timer.f = _wait_for_boot |
414 | + |
415 | + # call reset networking |
416 | + self.reset_network(instance) |
417 | + |
418 | return timer.start(interval=0.5, now=True) |
419 | |
420 | def _get_vm_opaque_ref(self, instance_or_vm): |
421 | @@ -398,6 +438,14 @@ |
422 | # TODO: implement this! |
423 | return 'http://fakeajaxconsole/fake_url' |
424 | |
425 | + def reset_network(self, instance): |
426 | + """ |
427 | + Creates uuid arg to pass to make_agent_call and calls it. |
428 | + |
429 | + """ |
430 | + args = {'id': str(uuid.uuid4())} |
431 | + resp = self._make_agent_call('resetnetwork', instance, '', args) |
432 | + |
433 | def list_from_xenstore(self, vm, path): |
434 | """Runs the xenstore-ls command to get a listing of all records |
435 | from 'path' downward. Returns a dict with the sub-paths as keys, |
436 | |
437 | === modified file 'nova/virt/xenapi_conn.py' |
438 | --- nova/virt/xenapi_conn.py 2011-01-25 23:20:55 +0000 |
439 | +++ nova/virt/xenapi_conn.py 2011-02-17 19:12:16 +0000 |
440 | @@ -188,6 +188,10 @@ |
441 | """resume the specified instance""" |
442 | self._vmops.resume(instance, callback) |
443 | |
444 | + def reset_network(self, instance): |
445 | + """reset networking for specified instance""" |
446 | + self._vmops.reset_network(instance) |
447 | + |
448 | def get_info(self, instance_id): |
449 | """Return data about VM instance""" |
450 | return self._vmops.get_info(instance_id) |
451 | |
452 | === modified file 'plugins/xenserver/xenapi/etc/xapi.d/plugins/agent' |
453 | --- plugins/xenserver/xenapi/etc/xapi.d/plugins/agent 2011-02-08 10:14:51 +0000 |
454 | +++ plugins/xenserver/xenapi/etc/xapi.d/plugins/agent 2011-02-17 19:12:16 +0000 |
455 | @@ -91,6 +91,18 @@ |
456 | return resp |
457 | |
458 | |
459 | +@jsonify |
460 | +def resetnetwork(self, arg_dict): |
461 | + """ |
462 | + Writes a resquest to xenstore that tells the agent to reset networking. |
463 | + |
464 | + """ |
465 | + arg_dict['value'] = json.dumps({'name': 'resetnetwork', 'value': ''}) |
466 | + request_id = arg_dict['id'] |
467 | + arg_dict['path'] = "data/host/%s" % request_id |
468 | + xenstore.write_record(self, arg_dict) |
469 | + |
470 | + |
471 | def _wait_for_agent(self, request_id, arg_dict): |
472 | """Periodically checks xenstore for a response from the agent. |
473 | The request is always written to 'data/host/{id}', and |
474 | @@ -124,4 +136,5 @@ |
475 | if __name__ == "__main__": |
476 | XenAPIPlugin.dispatch( |
477 | {"key_init": key_init, |
478 | - "password": password}) |
479 | + "password": password, |
480 | + "resetnetwork": resetnetwork}) |
Don't think I've ever seen a 5-space tabstop. Copy/paste error? :)
58 -# vim: tabstop=4 shiftwidth=4 softtabstop=4
59 +# vim: tabstop=5 shiftwidth=4 softtabstop=4
Please s/003_cactus/ 003_add_ network_ label_column/ for the migrate:
183 === added file 'nova/db/ sqlalchemy/ migrate_ repo/versions/ 003_cactus. py'
We need >1 migration file for a release, and naming the migration file with something that describes the schema changes in it is a common practice.
258 def create_ networks( self, context, cidr, num_networks, network_size,
259 - cidr_v6, *args, **kwargs):
260 + cidr_v6, label, *args, **kwargs):
Above, you have added label as a required argument to the network manager's create_networks() method, however:
1) I don't see where calls to create_networks() have been changed to pass in this newly-required label parameter
2) The label field of the Network model was added as an optional field, so it seems that perhaps the label param to create_networks() should have a default?
Other than those little things, the code looks good. Was there a plan for test code for this new functionality?
Cheers!
jay