Merge lp:~midokura/nova/network-service into lp:~ntt-pf-lab/nova/network-service
- network-service
- Merge into network-service
Proposed by
Ryu Ishimoto
Status: | Merged |
---|---|
Merge reported by: | Ryu Ishimoto |
Merged at revision: | not available |
Proposed branch: | lp:~midokura/nova/network-service |
Merge into: | lp:~ntt-pf-lab/nova/network-service |
Diff against target: |
1969 lines (+633/-357) 13 files modified
bin/nova-net-flat-vlan-manage (+192/-0) nova/api/ec2/cloud.py (+31/-9) nova/compute/api.py (+0/-6) nova/network/flat_vlan/api/__init__.py (+93/-7) nova/network/flat_vlan/common.py (+12/-0) nova/network/flat_vlan/compute.py (+7/-18) nova/network/flat_vlan/db/__init__.py (+1/-0) nova/network/flat_vlan/db/api.py (+84/-51) nova/network/flat_vlan/db/sqlalchemy/api.py (+14/-64) nova/network/flat_vlan/db/sqlalchemy/models.py (+48/-84) nova/network/flat_vlan/network.py (+87/-66) nova/network/service.py (+63/-48) nova/virt/libvirt_conn.py (+1/-4) |
To merge this branch: | bzr merge lp:~midokura/nova/network-service |
Related bugs: | |
Related blueprints: |
Refactor Networking
(Essential)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
NTT PF Lab. | Pending | ||
Review via email: mp+56616@code.launchpad.net |
Commit message
Added EC2 floating IP API support.
Description of the change
Added EC2 floating IP API support.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'bin/nova-net-flat-vlan-manage' |
2 | --- bin/nova-net-flat-vlan-manage 1970-01-01 00:00:00 +0000 |
3 | +++ bin/nova-net-flat-vlan-manage 2011-04-06 17:14:53 +0000 |
4 | @@ -0,0 +1,192 @@ |
5 | +#!/usr/bin/env python |
6 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
7 | + |
8 | +# Copyright 2011 Midokura KK |
9 | +# All Rights Reserved. |
10 | +# |
11 | +# Licensed under the Apache License, Version 2.0 (the "License"); you may |
12 | +# not use this file except in compliance with the License. You may obtain |
13 | +# a copy of the License at |
14 | +# |
15 | +# http://www.apache.org/licenses/LICENSE-2.0 |
16 | +# |
17 | +# Unless required by applicable law or agreed to in writing, software |
18 | +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
19 | +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
20 | +# License for the specific language governing permissions and limitations |
21 | +# under the License. |
22 | + |
23 | +# Interactive shell based on Django: |
24 | +# |
25 | +# Copyright (c) 2005, the Lawrence Journal-World |
26 | +# All rights reserved. |
27 | +# |
28 | +# Redistribution and use in source and binary forms, with or without |
29 | +# modification, are permitted provided that the following conditions are met: |
30 | +# |
31 | +# 1. Redistributions of source code must retain the above copyright notice, |
32 | +# this list of conditions and the following disclaimer. |
33 | +# |
34 | +# 2. Redistributions in binary form must reproduce the above copyright |
35 | +# notice, this list of conditions and the following disclaimer in the |
36 | +# documentation and/or other materials provided with the distribution. |
37 | +# |
38 | +# 3. Neither the name of Django nor the names of its contributors may be |
39 | +# used to endorse or promote products derived from this software without |
40 | +# specific prior written permission. |
41 | +# |
42 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
43 | +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
44 | +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
45 | +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
46 | +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
47 | +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
48 | +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
49 | +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
50 | +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
51 | +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
52 | +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
53 | + |
54 | + |
55 | +""" |
56 | + CLI interface for nova flat vlan network management. |
57 | +""" |
58 | + |
59 | +import gettext |
60 | +import os |
61 | +import sys |
62 | + |
63 | +import IPy |
64 | + |
65 | +# If ../nova/__init__.py exists, add ../ to Python search path, so that |
66 | +# it will override what happens to be installed in /usr/(local/)lib/python... |
67 | +possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), |
68 | + os.pardir, |
69 | + os.pardir)) |
70 | +if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): |
71 | + sys.path.insert(0, possible_topdir) |
72 | + |
73 | +gettext.install('nova', unicode=1) |
74 | + |
75 | +from nova import context |
76 | +from nova import db as nova_db |
77 | +from nova import exception |
78 | +from nova import flags as nova_flags |
79 | +from nova import log as logging |
80 | +from nova import utils |
81 | + |
82 | +from nova.network.flat_vlan import db |
83 | + |
84 | +NOVA_FLAGS = nova_flags.FLAGS |
85 | + |
86 | +class FloatingIpCommands(object): |
87 | + """Class for managing floating ip.""" |
88 | + |
89 | + def create(self, host, range): |
90 | + """Creates floating ips for host by range |
91 | + arguments: host ip_range""" |
92 | + for address in IPy.IP(range): |
93 | + db.floating_ip_create(context.get_admin_context(), |
94 | + {'address': str(address), |
95 | + 'host': host}) |
96 | + |
97 | + def delete(self, ip_range): |
98 | + """Deletes floating ips by range |
99 | + arguments: range""" |
100 | + for address in IPy.IP(ip_range): |
101 | + db.floating_ip_destroy(context.get_admin_context(), |
102 | + str(address)) |
103 | + |
104 | + def list(self, host=None): |
105 | + """Lists all floating ips (optionally by host) |
106 | + arguments: [host]""" |
107 | + ctxt = context.get_admin_context() |
108 | + if host == None: |
109 | + floating_ips = db.floating_ip_get_all(ctxt) |
110 | + else: |
111 | + floating_ips = db.floating_ip_get_all_by_host(ctxt, host) |
112 | + for floating_ip in floating_ips: |
113 | + instance_id = None |
114 | + fixed_ip = floating_ip['fixed_ip'] |
115 | + if fixed_ip and fixed_ip['ethernet_card_id']: |
116 | + vnic_id = fixed_ip['ethernet_card_id'] |
117 | + instance = nova_db.instance_get_by_virtual_nic(ctxt, |
118 | + vnic_id) |
119 | + instance_id = instance['ec2_id'] |
120 | + print "%s\t%s\t%s" % (floating_ip['host'], |
121 | + floating_ip['address'], |
122 | + instance_id) |
123 | + |
124 | + |
125 | +CATEGORIES = [ |
126 | + ('floating', FloatingIpCommands)] |
127 | + |
128 | +def lazy_match(name, key_value_tuples): |
129 | + """Finds all objects that have a key that case insensitively contains |
130 | + [name] key_value_tuples is a list of tuples of the form (key, value) |
131 | + returns a list of tuples of the form (key, value)""" |
132 | + result = [] |
133 | + for (k, v) in key_value_tuples: |
134 | + if k.lower().find(name.lower()) == 0: |
135 | + result.append((k, v)) |
136 | + if len(result) == 0: |
137 | + print "%s does not match any options:" % name |
138 | + for k, _v in key_value_tuples: |
139 | + print "\t%s" % k |
140 | + sys.exit(2) |
141 | + if len(result) > 1: |
142 | + print "%s matched multiple options:" % name |
143 | + for k, _v in result: |
144 | + print "\t%s" % k |
145 | + sys.exit(2) |
146 | + return result |
147 | + |
148 | +def methods_of(obj): |
149 | + """Get all callable methods of an object that don't start with underscore |
150 | + returns a list of tuples of the form (method_name, method)""" |
151 | + result = [] |
152 | + for i in dir(obj): |
153 | + if callable(getattr(obj, i)) and not i.startswith('_'): |
154 | + result.append((i, getattr(obj, i))) |
155 | + return result |
156 | + |
157 | + |
158 | +def main(): |
159 | + """Parse options and call the appropriate class/method.""" |
160 | + utils.default_flagfile() |
161 | + argv = NOVA_FLAGS(sys.argv) |
162 | + logging.setup() |
163 | + |
164 | + script_name = argv.pop(0) |
165 | + if len(argv) < 1: |
166 | + print script_name + " category action [<args>]" |
167 | + print "Available categories:" |
168 | + for k, _ in CATEGORIES: |
169 | + print "\t%s" % k |
170 | + sys.exit(2) |
171 | + category = argv.pop(0) |
172 | + matches = lazy_match(category, CATEGORIES) |
173 | + # instantiate the command group object |
174 | + category, fn = matches[0] |
175 | + command_object = fn() |
176 | + actions = methods_of(command_object) |
177 | + if len(argv) < 1: |
178 | + print script_name + " category action [<args>]" |
179 | + print "Available actions for %s category:" % category |
180 | + for k, _v in actions: |
181 | + print "\t%s" % k |
182 | + sys.exit(2) |
183 | + action = argv.pop(0) |
184 | + matches = lazy_match(action, actions) |
185 | + action, fn = matches[0] |
186 | + # call the action with the remaining arguments |
187 | + try: |
188 | + fn(*argv) |
189 | + sys.exit(0) |
190 | + except TypeError: |
191 | + print "Possible wrong number of arguments supplied" |
192 | + print "%s %s: %s" % (category, action, fn.__doc__) |
193 | + raise |
194 | + |
195 | +if __name__ == '__main__': |
196 | + main() |
197 | |
198 | === modified file 'nova/api/ec2/cloud.py' |
199 | --- nova/api/ec2/cloud.py 2011-03-24 20:20:15 +0000 |
200 | +++ nova/api/ec2/cloud.py 2011-04-06 17:14:53 +0000 |
201 | @@ -36,7 +36,8 @@ |
202 | from nova import exception |
203 | from nova import flags |
204 | from nova import log as logging |
205 | -from nova import network |
206 | +from nova.network import service as net_service |
207 | +from nova import quota |
208 | from nova import utils |
209 | from nova import volume |
210 | from nova.api.ec2 import ec2utils |
211 | @@ -82,10 +83,9 @@ |
212 | """ |
213 | def __init__(self): |
214 | self.image_service = s3.S3ImageService() |
215 | - self.network_api = network.API() |
216 | self.volume_api = volume.API() |
217 | self.compute_api = compute.API( |
218 | - network_api=self.network_api, |
219 | + network_api=None, |
220 | volume_api=self.volume_api, |
221 | hostname_factory=ec2utils.id_to_ec2_id) |
222 | self.setup() |
223 | @@ -767,26 +767,48 @@ |
224 | |
225 | def allocate_address(self, context, **kwargs): |
226 | LOG.audit(_("Allocate address"), context=context) |
227 | - public_ip = self.network_api.allocate_floating_ip(context) |
228 | + _, net_factory = net_service.get_service_factory(context, |
229 | + context.project_id) |
230 | + net_api_service = net_factory.get_api_service() |
231 | + ip_quota = quota.get_quota(context, context.project_id)['floating_ips'] |
232 | + try: |
233 | + public_ip = net_api_service.allocate_address(context, |
234 | + context.project_id, |
235 | + ip_quota) |
236 | + except quota.QuotaError, ex: |
237 | + LOG.warn(_("Quota exceeded for %s, tried to allocate " |
238 | + "address"), |
239 | + context.project_id) |
240 | + raise ex |
241 | + |
242 | return {'addressSet': [{'publicIp': public_ip}]} |
243 | |
244 | def release_address(self, context, public_ip, **kwargs): |
245 | LOG.audit(_("Release address %s"), public_ip, context=context) |
246 | - self.network_api.release_floating_ip(context, address=public_ip) |
247 | + _, net_factory = net_service.get_service_factory(context, |
248 | + context.project_id) |
249 | + net_api_service = net_factory.get_api_service() |
250 | + |
251 | + net_api_service.deallocate_address(context, public_ip) |
252 | return {'releaseResponse': ["Address released."]} |
253 | |
254 | def associate_address(self, context, instance_id, public_ip, **kwargs): |
255 | LOG.audit(_("Associate address %(public_ip)s to" |
256 | " instance %(instance_id)s") % locals(), context=context) |
257 | instance_id = ec2utils.ec2_id_to_id(instance_id) |
258 | - self.compute_api.associate_floating_ip(context, |
259 | - instance_id=instance_id, |
260 | - address=public_ip) |
261 | + vnic_ids = db.virtual_nics_get_by_instance(context, instance_id) |
262 | + _, net_factory = net_service.get_service_factory(context, |
263 | + context.project_id) |
264 | + net_api_service = net_factory.get_api_service() |
265 | + net_api_service.associate_address(context, vnic_ids[0], public_ip) |
266 | return {'associateResponse': ["Address associated."]} |
267 | |
268 | def disassociate_address(self, context, public_ip, **kwargs): |
269 | LOG.audit(_("Disassociate address %s"), public_ip, context=context) |
270 | - self.network_api.disassociate_floating_ip(context, address=public_ip) |
271 | + _, net_factory = net_service.get_service_factory(context, |
272 | + context.project_id) |
273 | + net_api_service = net_factory.get_api_service() |
274 | + net_api_service.disassociate_address(context, public_ip) |
275 | return {'disassociateResponse': ["Address disassociated."]} |
276 | |
277 | def run_instances(self, context, **kwargs): |
278 | |
279 | === modified file 'nova/compute/api.py' |
280 | --- nova/compute/api.py 2011-03-30 08:30:38 +0000 |
281 | +++ nova/compute/api.py 2011-04-06 17:14:53 +0000 |
282 | @@ -681,12 +681,6 @@ |
283 | "volume_id": volume_id}}) |
284 | return instance |
285 | |
286 | - def associate_floating_ip(self, context, instance_id, address): |
287 | - instance = self.get(context, instance_id) |
288 | - self.network_api.associate_floating_ip(context, |
289 | - floating_ip=address, |
290 | - fixed_ip=instance['fixed_ip']) |
291 | - |
292 | def get_instance_metadata(self, context, instance_id): |
293 | """Get all metadata associated with an instance.""" |
294 | rv = self.db.instance_metadata_get(context, instance_id) |
295 | |
296 | === modified file 'nova/network/flat_vlan/api/__init__.py' |
297 | --- nova/network/flat_vlan/api/__init__.py 2011-03-31 07:15:23 +0000 |
298 | +++ nova/network/flat_vlan/api/__init__.py 2011-04-06 17:14:53 +0000 |
299 | @@ -16,19 +16,26 @@ |
300 | # under the License. |
301 | from zope import interface |
302 | |
303 | +from nova import exception |
304 | +from nova import quota |
305 | +from nova import rpc |
306 | from nova.network import service |
307 | +from nova.network.flat_vlan import common |
308 | +from nova.network.flat_vlan import flags |
309 | from nova.network.flat_vlan import manager |
310 | -from nova.network.flat_vlan.db import api as db_api |
311 | +from nova.network.flat_vlan import db |
312 | + |
313 | +FLAGS = flags.FlagAccessor() |
314 | |
315 | class NetworkApiService(object): |
316 | """Network API Service for this plugin.""" |
317 | - |
318 | + |
319 | interface.implements(service.INetworkApiService) |
320 | |
321 | def create_vnic(self, context): |
322 | """Generic API to retrieve the default VNIC ID. |
323 | For flat simple network, create a new vNIC and return its ID. |
324 | - |
325 | + |
326 | Args: |
327 | context: Nova context object needed to access the DB. |
328 | |
329 | @@ -38,20 +45,99 @@ |
330 | # Create a new VNIC |
331 | vnic = manager.ethernet_card_create_with_random_mac(context) |
332 | return vnic.id |
333 | - |
334 | + |
335 | def get_project_vpn_address_and_port(self, context, project_id): |
336 | """Generic API to get network for a given project. |
337 | - |
338 | + |
339 | Args: |
340 | context: Nova context object needed to access the DB. |
341 | project_id: project to get the VPN IP and port for. |
342 | - |
343 | + |
344 | Returns: |
345 | A tuple of VPN IP address and port number. |
346 | """ |
347 | - network = db_api.network_get_by_project(context, project_id) |
348 | + network = db.network_get_by_project(context, project_id) |
349 | if network: |
350 | return (network['vpn_public_address'], network['vpn_public_port']) |
351 | else: |
352 | return (None, None) |
353 | |
354 | + def allocate_address(self, context, project_id, ip_quota): |
355 | + """Gets the number of floating IPs associated with a project. |
356 | + |
357 | + Args: |
358 | + context: Nova context object needed to access the DB. |
359 | + project_id: Project to allocate the address from. |
360 | + ip_quota: Quota for IP addresses. |
361 | + |
362 | + Returns: |
363 | + An IP address. |
364 | + |
365 | + Raises: |
366 | + quota.QuotaError: Over the quota limit. |
367 | + """ |
368 | + used_floating_ips = db.floating_ip_count_by_project(context, |
369 | + project_id) |
370 | + allowed_floating_ips = min(1, ip_quota - used_floating_ips) |
371 | + if allowed_floating_ips < 1: |
372 | + raise quota.QuotaError(_("Quota exceeeded for %s, tried to allocate" |
373 | + " address"), project_id) |
374 | + |
375 | + # Let the network service handle this because the DB update requires the |
376 | + # network service host name. |
377 | + host = rpc.call(context, |
378 | + FLAGS.net_flat_vlan_network_topic, |
379 | + {"method": "get_host"}) |
380 | + |
381 | + ip = db.floating_ip_allocate_address(context, host, project_id) |
382 | + return ip.address |
383 | + |
384 | + def deallocate_address(self, context, floating_address): |
385 | + """Deallocates the public IP address by removing it from any |
386 | + project. |
387 | + |
388 | + Args: |
389 | + context: nova context object needed to access the DB. |
390 | + address: Public IP address to deallocate. |
391 | + """ |
392 | + db.floating_ip_deallocate(context, floating_address) |
393 | + |
394 | + def associate_address(self, context, vnic_id, floating_address): |
395 | + """Associates a floating address to the fixed IP address of the vnic. |
396 | + |
397 | + Args: |
398 | + context: Nova context object |
399 | + vnic_id: virtual NIC ID |
400 | + floating_address: public IP address to assign to the VNIC. |
401 | + """ |
402 | + fixed_ip = db.fixed_ip_get_by_ethernet_card(context, vnic_id) |
403 | + floating_ip = db.floating_ip_get_by_address(context, floating_address) |
404 | + db.floating_ip_fixed_ip_associate(context, floating_ip['address'], |
405 | + fixed_ip['address']) |
406 | + |
407 | + host = fixed_ip['network']['host'] |
408 | + rpc.cast(context, |
409 | + common.queue_get_for(FLAGS.net_flat_vlan_network_topic, |
410 | + host), |
411 | + {"method": "activate_public_ip", |
412 | + "args": {"floating_address": floating_ip['address'], |
413 | + "fixed_address": fixed_ip['address']}}) |
414 | + |
415 | + def disassociate_address(self, context, floating_address): |
416 | + """Diassociates public IP. |
417 | + |
418 | + Args: |
419 | + context: Nova context object |
420 | + floating_address: public IP address |
421 | + """ |
422 | + floating_ip = db.floating_ip_get_by_address(context, floating_address) |
423 | + if not floating_ip.get('fixed_ip'): |
424 | + raise exception.ApiError('Address is not associated.') |
425 | + fixed_ip = db.floating_ip_disassociate(context, floating_address) |
426 | + host = fixed_ip['network']['host'] |
427 | + rpc.cast(context, |
428 | + common.queue_get_for(FLAGS.net_flat_vlan_network_topic, |
429 | + host), |
430 | + {"method": "deactivate_public_ip", |
431 | + "args": {"floating_address": floating_ip['address'], |
432 | + "fixed_address": fixed_ip['address']}}) |
433 | |
434 | === modified file 'nova/network/flat_vlan/common.py' |
435 | --- nova/network/flat_vlan/common.py 2011-03-31 09:36:57 +0000 |
436 | +++ nova/network/flat_vlan/common.py 2011-04-06 17:14:53 +0000 |
437 | @@ -44,3 +44,15 @@ |
438 | """ |
439 | net = IPy.IP(cidr) |
440 | return str(net.net()), str(net.netmask()) |
441 | + |
442 | +def queue_get_for(topic, physical_node_id): |
443 | + """Gets the queue name for RPC. |
444 | + |
445 | + Args: |
446 | + topic: Topic to listen to |
447 | + physical_node_id: Node ID to listen to. |
448 | + |
449 | + Returns: |
450 | + The queue name to send the RPC to. |
451 | + """ |
452 | + return "%s.%s" % (topic, physical_node_id) |
453 | \ No newline at end of file |
454 | |
455 | === modified file 'nova/network/flat_vlan/compute.py' |
456 | --- nova/network/flat_vlan/compute.py 2011-04-04 09:52:18 +0000 |
457 | +++ nova/network/flat_vlan/compute.py 2011-04-06 17:14:53 +0000 |
458 | @@ -26,18 +26,6 @@ |
459 | |
460 | FLAGS = flags.FlagAccessor() |
461 | |
462 | -def _queue_get_for(topic, physical_node_id): |
463 | - """Gets the queue name for RPC. |
464 | - |
465 | - Args: |
466 | - topic: Topic to listen to |
467 | - physical_node_id: Node ID to listen to. |
468 | - |
469 | - Returns: |
470 | - The queue name to send the RPC to. |
471 | - """ |
472 | - return "%s.%s" % (topic, physical_node_id) |
473 | - |
474 | def _get_network_topic(context, **kwargs): |
475 | """Retrieves the network host for a project on this host |
476 | |
477 | @@ -51,8 +39,8 @@ |
478 | host = FLAGS.net_flat_vlan_network_host |
479 | else: |
480 | host = _get_network_host(context) |
481 | - return _queue_get_for(FLAGS.net_flat_vlan_network_topic, |
482 | - host) |
483 | + return common.queue_get_for(FLAGS.net_flat_vlan_network_topic, |
484 | + host) |
485 | |
486 | def _set_network_host(context, network_id): |
487 | """Safely sets the host of the network. |
488 | @@ -87,8 +75,8 @@ |
489 | FLAGS.net_flat_vlan_network_bridge) |
490 | host = network_ref['host'] |
491 | if not host: |
492 | - topic = _queue_get_for(FLAGS.net_flat_vlan_network_topic, |
493 | - FLAGS.net_flat_vlan_network_host) |
494 | + topic = common.queue_get_for(FLAGS.net_flat_vlan_network_topic, |
495 | + FLAGS.net_flat_vlan_network_host) |
496 | if FLAGS.net_flat_vlan_network_fake_call: |
497 | return _set_network_host(context, network_ref['id']) |
498 | host = rpc.call(context, |
499 | @@ -146,7 +134,8 @@ |
500 | vnic_ids: list of VNIC IDs |
501 | """ |
502 | for vnic_id in vnic_ids: |
503 | - fixed_ip = vnic_id.get('fixed_ip') |
504 | + vnic_ref = db_api.ethernet_card_get(context, vnic_id) |
505 | + fixed_ip = vnic_ref.get('fixed_ip') |
506 | if not FLAGS.stub_network and fixed_ip: |
507 | |
508 | if (FLAGS.net_flat_vlan_use_vlan or |
509 | @@ -156,7 +145,7 @@ |
510 | for floating_ip in floating_ips: |
511 | address = floating_ip['address'] |
512 | |
513 | - network_topic = _queue_get_for(context, |
514 | + network_topic = common.queue_get_for(context, |
515 | FLAGS.net_flat_vlan_network_topic, |
516 | floating_ip['host']) |
517 | |
518 | |
519 | === modified file 'nova/network/flat_vlan/db/__init__.py' |
520 | --- nova/network/flat_vlan/db/__init__.py 2011-03-31 06:18:29 +0000 |
521 | +++ nova/network/flat_vlan/db/__init__.py 2011-04-06 17:14:53 +0000 |
522 | @@ -18,3 +18,4 @@ |
523 | DB abstraction for Flat VLAN network service |
524 | """ |
525 | |
526 | +from nova.network.flat_vlan.db.api import * |
527 | |
528 | === modified file 'nova/network/flat_vlan/db/api.py' |
529 | --- nova/network/flat_vlan/db/api.py 2011-04-02 19:01:17 +0000 |
530 | +++ nova/network/flat_vlan/db/api.py 2011-04-06 17:14:53 +0000 |
531 | @@ -19,85 +19,95 @@ |
532 | |
533 | The underlying driver is loaded as a :class:`LazyPluggable`. |
534 | """ |
535 | +from nova import exception |
536 | from nova import utils |
537 | +from nova.db.sqlalchemy import api as nova_api |
538 | from nova.network.flat_vlan import flags |
539 | |
540 | FLAGS = flags.FlagAccessor() |
541 | |
542 | -IMPL = utils.LazyPluggable(FLAGS.get('net_flat_vlan_db_backend'), |
543 | - sqlalchemy='nova.network.flat_vlan.db.sqlalchemy.api') |
544 | +IMPL = utils.LazyPluggable( |
545 | + FLAGS.get('net_flat_vlan_db_backend'), |
546 | + sqlalchemy='nova.network.flat_vlan.db.sqlalchemy.api') |
547 | |
548 | ################### |
549 | |
550 | def ethernet_card_get(context, id): |
551 | """Get ethernet card by id.""" |
552 | - return IMPL.dao_factory.get_dao(context).\ |
553 | + return IMPL.dao_factory.get_dao().\ |
554 | ethernet_card_get(id) |
555 | |
556 | def ethernet_card_create(context, values): |
557 | """Create a new ethernet card.""" |
558 | - return IMPL.dao_factory.get_dao(context).\ |
559 | + return IMPL.dao_factory.get_dao().\ |
560 | ethernet_card_create(values) |
561 | |
562 | def ethernet_card_get_all(context): |
563 | """Get all ethernet cards.""" |
564 | - return IMPL.dao_factory.get_dao(context).\ |
565 | - ethernet_card_get_all() |
566 | + can_read_deleted = nova_api.can_read_deleted(context) |
567 | + return IMPL.dao_factory.get_dao().\ |
568 | + ethernet_card_get_all(read_deleted=can_read_deleted) |
569 | |
570 | def ethernet_card_update(context, ethernet_card_id, values): |
571 | """Update ethernet card.""" |
572 | - return IMPL.dao_factory.get_dao(context).\ |
573 | + return IMPL.dao_factory.get_dao().\ |
574 | ethernet_card_update(ethernet_card_id, values) |
575 | |
576 | def ethernet_card_delete(context, ethernet_card_id): |
577 | """Delete ethernet card.""" |
578 | - return IMPL.dao_factory.get_dao(context).\ |
579 | + return IMPL.dao_factory.get_dao().\ |
580 | ethernet_card_delete(ethernet_card_id) |
581 | |
582 | def network_get(context, id): |
583 | """Get network by id.""" |
584 | - return IMPL.dao_factory.get_dao(context).\ |
585 | + return IMPL.dao_factory.get_dao().\ |
586 | network_get(id) |
587 | |
588 | +@nova_api.require_admin_context |
589 | def network_get_by_ethernet_card(context, ethernet_card_id): |
590 | """Get network by ethernet card.""" |
591 | - return IMPL.dao_factory.get_dao(context).\ |
592 | + return IMPL.dao_factory.get_dao().\ |
593 | network_get_by_ethernet_card(ethernet_card_id) |
594 | |
595 | +@nova_api.require_admin_context |
596 | def network_get_associated_fixed_ips(context, network_id): |
597 | """Get fixed IPs that are associated with ethernet for a given network.""" |
598 | - return IMPL.dao_factory.get_dao(context).\ |
599 | + return IMPL.dao_factory.get_dao().\ |
600 | network_get_associated_fixed_ips(network_id) |
601 | |
602 | def host_get_networks(context, host): |
603 | """Get networks for a given host.""" |
604 | - return IMPL.dao_factory.get_dao(context).\ |
605 | + return IMPL.dao_factory.get_dao().\ |
606 | host_get_networks(host) |
607 | |
608 | +@nova_api.require_admin_context |
609 | def network_get_by_bridge(context, bridge): |
610 | """Get a network by bridge or raise if it does not exist.""" |
611 | - return IMPL.dao_factory.get_dao(context).\ |
612 | + return IMPL.dao_factory.get_dao().\ |
613 | network_get_by_bridge(bridge) |
614 | |
615 | +@nova_api.require_admin_context |
616 | def network_get_by_cidr(context, cidr): |
617 | """Get a network by cidr.""" |
618 | - return IMPL.dao_factory.get_dao(context).\ |
619 | + return IMPL.dao_factory.get_dao().\ |
620 | network_get_by_cidr(cidr) |
621 | |
622 | def network_create(context, values): |
623 | """Create a new network.""" |
624 | - return IMPL.dao_factory.get_dao(context).\ |
625 | + return IMPL.dao_factory.get_dao().\ |
626 | network_create(values) |
627 | |
628 | +@nova_api.require_admin_context |
629 | def network_create_safe(context, values): |
630 | """Create a new network. Returns None when there is an exception""" |
631 | - return IMPL.dao_factory.get_dao(context).\ |
632 | + return IMPL.dao_factory.get_dao().\ |
633 | network_create_safe(values) |
634 | |
635 | def network_get_all(context): |
636 | """Get all networks.""" |
637 | - return IMPL.dao_factory.get_dao(context).\ |
638 | - network_get_all() |
639 | + can_read_deleted = nova_api.can_read_deleted(context) |
640 | + return IMPL.dao_factory.get_dao().\ |
641 | + network_get_all(read_deleted=can_read_deleted) |
642 | |
643 | def network_get_by_project(context, project_id, associate=True): |
644 | """Return the network associated with the project. |
645 | @@ -106,22 +116,25 @@ |
646 | network if one is not found, otherwise it returns None. |
647 | |
648 | """ |
649 | - return IMPL.dao_factory.get_dao(context).\ |
650 | + if associate and not nova_api.is_admin_context(context): |
651 | + raise exception.NotAuthorized() |
652 | + return IMPL.dao_factory.get_dao().\ |
653 | network_get_by_project(project_id, associate) |
654 | |
655 | def network_update(context, network_id, values): |
656 | """Update network.""" |
657 | - return IMPL.dao_factory.get_dao(context).\ |
658 | + return IMPL.dao_factory.get_dao().\ |
659 | network_update(network_id, values) |
660 | |
661 | def network_delete(context, network_id): |
662 | """Delete network.""" |
663 | - return IMPL.dao_factory.get_dao(context).\ |
664 | + return IMPL.dao_factory.get_dao().\ |
665 | network_delete(network_id) |
666 | |
667 | +@nova_api.require_admin_context |
668 | def network_associate(context, project_id): |
669 | """Associate a free network to a project.""" |
670 | - return IMPL.dao_factory.get_dao(context).\ |
671 | + return IMPL.dao_factory.get_dao().\ |
672 | network_associate(project_id) |
673 | |
674 | def floating_ip_allocate_address(context, host, project_id): |
675 | @@ -130,32 +143,38 @@ |
676 | Raises if one is not available. |
677 | |
678 | """ |
679 | - return IMPL.dao_factory.get_dao(context).\ |
680 | + nova_api.authorize_project_context(context, project_id) |
681 | + return IMPL.dao_factory.get_dao().\ |
682 | floating_ip_allocate_address(host, project_id) |
683 | |
684 | def floating_ip_create(context, values): |
685 | """Create a floating ip from the values dictionary.""" |
686 | - return IMPL.dao_factory.get_dao(context).\ |
687 | + return IMPL.dao_factory.get_dao().\ |
688 | floating_ip_create(values) |
689 | |
690 | def floating_ip_count_by_project(context, project_id): |
691 | """Count floating ips used by project.""" |
692 | - return IMPL.dao_factory.get_dao(context).\ |
693 | + nova_api.authorize_project_context(context, project_id) |
694 | + return IMPL.dao_factory.get_dao().\ |
695 | floating_ip_count_by_project(project_id) |
696 | |
697 | def floating_ip_deallocate(context, address): |
698 | """Deallocate an floating ip by address""" |
699 | - return IMPL.dao_factory.get_dao(context).\ |
700 | + # TODO(devcamcar): How to ensure floating id belongs to user? |
701 | + return IMPL.dao_factory.get_dao().\ |
702 | floating_ip_deallocate(address) |
703 | |
704 | def floating_ip_destroy(context, address): |
705 | """Destroy the floating_ip or raise if it does not exist.""" |
706 | - return IMPL.dao_factory.get_dao(context).\ |
707 | + # TODO(devcamcar): Ensure address belongs to user. |
708 | + return IMPL.dao_factory.get_dao().\ |
709 | floating_ip_destroy(address) |
710 | |
711 | def floating_ip_disassociate(context, floating_ip_id): |
712 | """Diassociate the floating_ip.""" |
713 | - return IMPL.dao_factory.get_dao(context).\ |
714 | + # TODO(devcamcar): Ensure address belongs to user. |
715 | + # Does get_floating_ip_by_address handle this? |
716 | + return IMPL.dao_factory.get_dao().\ |
717 | floating_ip_disassociate(floating_ip_id) |
718 | |
719 | def floating_ip_disassociate_by_address(context, address): |
720 | @@ -164,91 +183,105 @@ |
721 | Returns the address of the existing fixed ip. |
722 | |
723 | """ |
724 | - return IMPL.dao_factory.get_dao(context).\ |
725 | + # TODO(devcamcar): Ensure address belongs to user. |
726 | + # Does get_floating_ip_by_address handle this? |
727 | + return IMPL.dao_factory.get_dao().\ |
728 | floating_ip_disassociate_by_address(address) |
729 | |
730 | def floating_ip_fixed_ip_associate(context, floating_address, fixed_address): |
731 | """Associate an floating ip to a fixed_ip by address.""" |
732 | - return IMPL.dao_factory.get_dao(context).\ |
733 | + # TODO(devcamcar): How to ensure floating_id belongs to user? |
734 | + return IMPL.dao_factory.get_dao().\ |
735 | floating_ip_fixed_ip_associate(floating_address, fixed_address) |
736 | |
737 | +@nova_api.require_admin_context |
738 | def floating_ip_get_all(context): |
739 | """Get all floating ips.""" |
740 | - return IMPL.dao_factory.get_dao(context).\ |
741 | + return IMPL.dao_factory.get_dao().\ |
742 | floating_ip_get_all() |
743 | |
744 | +@nova_api.require_admin_context |
745 | def floating_ip_get_all_by_host(context, host): |
746 | """Get all floating ips by host.""" |
747 | - return IMPL.dao_factory.get_dao(context).\ |
748 | + return IMPL.dao_factory.get_dao().\ |
749 | floating_ip_get_all_by_host(host) |
750 | |
751 | def floating_ip_get_all_by_project(context, project_id): |
752 | """Get all floating ips by project.""" |
753 | - return IMPL.dao_factory.get_dao(context).\ |
754 | + nova_api.authorize_project_context(context, project_id) |
755 | + return IMPL.dao_factory.get_dao().\ |
756 | floating_ip_get_all_by_project(project_id) |
757 | |
758 | def floating_ip_get_by_address(context, address): |
759 | """Get a floating ip by address or raise if it doesn't exist.""" |
760 | - return IMPL.dao_factory.get_dao(context).\ |
761 | - floating_ip_get_by_address(address) |
762 | + # TODO(devcamcar): Ensure the address belongs to user. |
763 | + can_read_deleted = nova_api.can_read_deleted(context) |
764 | + return IMPL.dao_factory.get_dao().\ |
765 | + floating_ip_get_by_address(address, read_deleted=can_read_deleted) |
766 | |
767 | def floating_ip_update(context, address, values): |
768 | """Update a floating ip by address or raise if it doesn't exist.""" |
769 | - return IMPL.dao_factory.get_dao(context).\ |
770 | + return IMPL.dao_factory.get_dao().\ |
771 | floating_ip_update(address, values) |
772 | |
773 | def fixed_ip_create(context, values): |
774 | """Creates a fixed IP.""" |
775 | - return IMPL.dao_factory.get_dao(context).\ |
776 | + return IMPL.dao_factory.get_dao().\ |
777 | fixed_ip_create(values) |
778 | |
779 | def fixed_ip_get(context, fixed_ip_id): |
780 | """Gets fixed IP with ID.""" |
781 | - return IMPL.dao_factory.get_dao(context).\ |
782 | + return IMPL.dao_factory.get_dao().\ |
783 | fixed_ip_get(fixed_ip_id) |
784 | |
785 | def fixed_ip_get_all(context): |
786 | """Gets all the fixed IPs.""" |
787 | - return IMPL.dao_factory.get_dao(context).\ |
788 | + return IMPL.dao_factory.get_dao().\ |
789 | fixed_ip_get_all() |
790 | |
791 | def fixed_ip_get_by_address(context, address): |
792 | """Get fixed IP by address.""" |
793 | - return IMPL.dao_factory.get_dao(context).\ |
794 | - fixed_ip_get_by_address(address) |
795 | + can_read_deleted = nova_api.can_read_deleted(context) |
796 | + return IMPL.dao_factory.get_dao().\ |
797 | + fixed_ip_get_by_address(address, read_deleted=can_read_deleted) |
798 | |
799 | def fixed_ip_get_by_ethernet_card(context, ethernet_card_id): |
800 | """Get IP address by ethernet card id.""" |
801 | - return IMPL.dao_factory.get_dao(context).\ |
802 | - fixed_ip_get_by_ethernet_card(ethernet_card_id) |
803 | + can_read_deleted = nova_api.can_read_deleted(context) |
804 | + return IMPL.dao_factory.get_dao().\ |
805 | + fixed_ip_get_by_ethernet_card(ethernet_card_id, |
806 | + read_deleted=can_read_deleted) |
807 | |
808 | +@nova_api.require_admin_context |
809 | def fixed_ip_get_network(context, address): |
810 | """Gets network of an IP address.""" |
811 | - return IMPL.dao_factory.get_dao(context).\ |
812 | - fixed_ip_get_network(address) |
813 | + can_read_deleted = nova_api.can_read_deleted(context) |
814 | + return IMPL.dao_factory.get_dao().\ |
815 | + fixed_ip_get_network(address, read_deleted=can_read_deleted) |
816 | |
817 | def fixed_ip_update(context, fixed_ip_id, values): |
818 | """Update fixed IP.""" |
819 | - return IMPL.dao_factory.get_dao(context).\ |
820 | + return IMPL.dao_factory.get_dao().\ |
821 | fixed_ip_update(fixed_ip_id, values) |
822 | |
823 | def fixed_ip_disassociate(context, fixed_ip_id): |
824 | """Removes reference to ethernet card from IP.""" |
825 | - return IMPL.dao_factory.get_dao(context).\ |
826 | + return IMPL.dao_factory.get_dao().\ |
827 | fixed_ip_disassociate(fixed_id_ip) |
828 | |
829 | def fixed_ip_associate(context, fixed_ip_id, ethernet_card_id): |
830 | """Associates an IP address to an ethernet card.""" |
831 | - return IMPL.dao_factory.get_dao(context).\ |
832 | + return IMPL.dao_factory.get_dao().\ |
833 | fixed_ip_associate(fixed_ip_id, ethernet_card_id) |
834 | |
835 | +@nova_api.require_admin_context |
836 | def fixed_ip_associate_pool(context, network_id, ethernet_card_id): |
837 | """Associates an IP to an ethernet card.""" |
838 | - return IMPL.dao_factory.get_dao(context).\ |
839 | + return IMPL.dao_factory.get_dao().\ |
840 | fixed_ip_associate_pool(network_id, ethernet_card_id) |
841 | |
842 | +@nova_api.require_admin_context |
843 | def fixed_ip_disassociate_all_by_timeout(context, host, time): |
844 | """Disassociates fixed IP by timeout.""" |
845 | - return IMPL.dao_factory.get_dao(context).\ |
846 | + return IMPL.dao_factory.get_dao().\ |
847 | fixed_ip_disassociate_all_by_timeout(host, time) |
848 | - |
849 | \ No newline at end of file |
850 | |
851 | === modified file 'nova/network/flat_vlan/db/sqlalchemy/api.py' |
852 | --- nova/network/flat_vlan/db/sqlalchemy/api.py 2011-04-02 17:11:15 +0000 |
853 | +++ nova/network/flat_vlan/db/sqlalchemy/api.py 2011-04-06 17:14:53 +0000 |
854 | @@ -17,81 +17,31 @@ |
855 | """ |
856 | Implementation of SQLAlchemy backend. |
857 | """ |
858 | - |
859 | -from sqlalchemy import or_ |
860 | -from sqlalchemy.exc import IntegrityError |
861 | -from sqlalchemy.orm import joinedload_all |
862 | -import warnings |
863 | - |
864 | -from nova import exception |
865 | -from nova.db import api as nova_db |
866 | -from nova.db.sqlalchemy import api as nova_api |
867 | from nova.network.flat_vlan.db.sqlalchemy import models |
868 | from nova.network.flat_vlan.db.sqlalchemy.session import get_session |
869 | |
870 | |
871 | -class DataAccessCache(object): |
872 | - """A cache of Data Access Objects specific to sessions and contexts. |
873 | - |
874 | - Creates one DAO object per session and set of context parameter |
875 | - values, and caches it. The parameters currently used in the |
876 | - context are: |
877 | - - nova.db.sqlalchemy.api.is_admin_context(context) |
878 | - - nova.db.sqlalchemy.api.can_read_deleted(context) |
879 | - """ |
880 | - |
881 | - def __init__(self, dao_class): |
882 | - self._dao_class = dao_class |
883 | - self._cached_daos = {} |
884 | - |
885 | - def get_dao(self, context, session): |
886 | - """Get a DataAccess object. |
887 | - |
888 | - If no cached DAO has been created for this session and this |
889 | - context's parameter, a new DAO is created and |
890 | - cached. Otherwise, the cached DAO is returned. |
891 | - |
892 | - :param context: The request context. |
893 | - :param session: The SQLAlchemy session to use as the Data |
894 | - Access Object's data source. |
895 | - """ |
896 | - is_admin = nova_api.is_admin_context(context) |
897 | - can_read_deleted = nova_api.can_read_deleted(context) |
898 | - key = (session, is_admin, can_read_deleted) |
899 | - dao = self._cached_daos.get(key) |
900 | - if dao is None: |
901 | - dao = self._dao_class(session, is_admin, can_read_deleted) |
902 | - self._cached_daos[key] = dao |
903 | - return dao |
904 | - |
905 | - |
906 | -class DefaultSessionNetworkDataAccessFactory(object): |
907 | - """A DAO factory that lazily uses the default session. |
908 | +class DefaultSessionFlatVlanNetworkDataAccessFactory(object): |
909 | + """A DAO factory that lazily creates and uses the default session. |
910 | |
911 | This factory uses the default session for the flat VLAN network |
912 | service, which it creates lazily when creating the first DAO. |
913 | """ |
914 | |
915 | def __init__(self): |
916 | - self._dao_cache = DataAccessCache(models.FlatVlanNetworkDataAccess) |
917 | - self._session = None |
918 | - |
919 | - def get_session(self): |
920 | - if self._session is None: |
921 | - self._session = get_session() |
922 | - return self._session |
923 | - |
924 | - def get_dao(self, context): |
925 | + self._dao = None |
926 | + |
927 | + def get_dao(self): |
928 | """Get a DataAccess object. |
929 | |
930 | - If no cached DAO has been created for this context's |
931 | - parameter, a new DAO is created and cached. Otherwise, the |
932 | - cached DAO is returned. |
933 | - |
934 | - :param context: The request context. |
935 | + If no cached DAO has been created for the default session, a |
936 | + new DAO is created and cached. Otherwise, the cached DAO is |
937 | + returned. |
938 | """ |
939 | - return self._dao_cache.get_dao(context, self.get_session()) |
940 | - |
941 | - |
942 | -dao_factory = DefaultSessionNetworkDataAccessFactory() |
943 | + if self._dao is None: |
944 | + self._dao = models.FlatVlanNetworkDataAccess(get_session()) |
945 | + return self._dao |
946 | + |
947 | + |
948 | +dao_factory = DefaultSessionFlatVlanNetworkDataAccessFactory() |
949 | |
950 | |
951 | === modified file 'nova/network/flat_vlan/db/sqlalchemy/models.py' |
952 | --- nova/network/flat_vlan/db/sqlalchemy/models.py 2011-04-04 09:52:18 +0000 |
953 | +++ nova/network/flat_vlan/db/sqlalchemy/models.py 2011-04-06 17:14:53 +0000 |
954 | @@ -22,6 +22,7 @@ |
955 | from sqlalchemy.orm import joinedload, joinedload_all |
956 | from sqlalchemy import Column, Boolean, Integer, String |
957 | from sqlalchemy import ForeignKey |
958 | +from sqlalchemy.exc import IntegrityError |
959 | from sqlalchemy.ext.declarative import declarative_base |
960 | |
961 | from nova import exception |
962 | @@ -91,26 +92,20 @@ |
963 | 'FloatingIp.fixed_ip_id == FixedIp.id,' |
964 | 'FloatingIp.deleted == False)') |
965 | project_id = Column(String(255)) |
966 | - host = Column(String(255)) # , ForeignKey('hosts.id')) |
967 | + host = Column(String(255)) # , ForeignKey('hosts.id')) |
968 | |
969 | |
970 | class DataAccess(object): |
971 | """The base class to implement Data Access Objects. |
972 | """ |
973 | |
974 | - def __init__(self, session, is_admin, can_read_deleted): |
975 | + def __init__(self, session): |
976 | """Initialize this Data Access Object. |
977 | |
978 | :param session: The SQLAlchemy session to use as this Data |
979 | Access Object's data source. |
980 | - :param is_admin: Indicates if the request context is an |
981 | - administrator. |
982 | - :param can_read_deleted: Indicates if the request context has |
983 | - access to deleted objects. |
984 | """ |
985 | self._session = session |
986 | - self._is_admin = is_admin |
987 | - self._can_read_deleted = can_read_deleted |
988 | |
989 | |
990 | class EthernetCardDataAccess(DataAccess): |
991 | @@ -130,9 +125,9 @@ |
992 | |
993 | return result |
994 | |
995 | - def ethernet_card_get_all(self): |
996 | + def ethernet_card_get_all(self, read_deleted=False): |
997 | return self._session.query(self.ethernet_card_dto_class).\ |
998 | - filter_by(deleted=self._can_read_deleted).\ |
999 | + filter_by(deleted=read_deleted).\ |
1000 | all() |
1001 | |
1002 | def ethernet_card_create(self, values): |
1003 | @@ -171,8 +166,6 @@ |
1004 | return result |
1005 | |
1006 | def network_get_by_bridge(self, bridge): |
1007 | - if not self._is_admin: |
1008 | - raise exception.NotAuthorized() |
1009 | result = self._session.query(self.network_dto_class).\ |
1010 | filter_by(bridge=bridge).\ |
1011 | filter_by(deleted=False).\ |
1012 | @@ -184,8 +177,6 @@ |
1013 | return result |
1014 | |
1015 | def network_get_by_ethernet_card(self, ethernet_card_id): |
1016 | - if not self._is_admin: |
1017 | - raise exception.NotAuthorized() |
1018 | rv = self._session.query(self.network_dto_class).\ |
1019 | filter_by(deleted=False).\ |
1020 | join(self.network_dto_class.fixed_ips).\ |
1021 | @@ -193,7 +184,7 @@ |
1022 | filter_by(deleted=False).\ |
1023 | first() |
1024 | if not rv: |
1025 | - raise exception.NotFound(_('No network for ethernet card %s') % |
1026 | + raise exception.NotFound(_('No network for ethernet card %s') % |
1027 | ethernet_card_id) |
1028 | return rv |
1029 | |
1030 | @@ -204,9 +195,9 @@ |
1031 | filter_by(host=host).\ |
1032 | all() |
1033 | |
1034 | - def network_get_all(self): |
1035 | + def network_get_all(self, read_deleted=False): |
1036 | return self._session.query(self.network_dto_class).\ |
1037 | - filter_by(deleted=self._can_read_deleted).\ |
1038 | + filter_by(deleted=read_deleted).\ |
1039 | all() |
1040 | |
1041 | def network_create(self, values): |
1042 | @@ -216,8 +207,6 @@ |
1043 | return network_ref |
1044 | |
1045 | def network_create_safe(self, values): |
1046 | - if not self._is_admin: |
1047 | - raise exception.NotAuthorized() |
1048 | try: |
1049 | return self.network_create(values) |
1050 | except IntegrityError: |
1051 | @@ -272,8 +261,6 @@ |
1052 | return result |
1053 | |
1054 | def network_get_associated_fixed_ips(self, network_id): |
1055 | - if not self._is_admin: |
1056 | - raise exception.NotAuthorized() |
1057 | return self._session.query(self.fixed_ip_dto_class).\ |
1058 | options(joinedload_all('ethernet_card')).\ |
1059 | filter_by(network_id=network_id).\ |
1060 | @@ -283,10 +270,10 @@ |
1061 | |
1062 | network_get_associated_ips = network_get_associated_fixed_ips |
1063 | |
1064 | - def fixed_ip_get_by_address(self, address): |
1065 | + def fixed_ip_get_by_address(self, address, read_deleted=False): |
1066 | result = self._session.query(self.fixed_ip_dto_class).\ |
1067 | filter_by(address=address).\ |
1068 | - filter_by(deleted=self._can_read_deleted).\ |
1069 | + filter_by(deleted=read_deleted).\ |
1070 | options(joinedload('network')).\ |
1071 | options(joinedload('ethernet_card')).\ |
1072 | first() |
1073 | @@ -301,16 +288,15 @@ |
1074 | fixed_ip_ref.ethernet_card = None |
1075 | fixed_ip_ref.save(session=self._session) |
1076 | |
1077 | - def fixed_ip_get_by_ethernet_card(self, ethernet_card_id): |
1078 | + def fixed_ip_get_by_ethernet_card(self, ethernet_card_id, |
1079 | + read_deleted=False): |
1080 | result = self._session.query(self.fixed_ip_dto_class).\ |
1081 | filter_by(ethernet_card_id=ethernet_card_id).\ |
1082 | - filter_by(deleted=self._can_read_deleted).\ |
1083 | + filter_by(deleted=read_deleted).\ |
1084 | first() |
1085 | return result |
1086 | |
1087 | def fixed_ip_disassociate_all_by_timeout(self, host, time): |
1088 | - if not self._is_admin: |
1089 | - raise exception.NotAuthorized() |
1090 | inner_q = self._session.query(Network.id).\ |
1091 | filter_by(host=host).\ |
1092 | subquery() |
1093 | @@ -330,53 +316,46 @@ |
1094 | |
1095 | floating_ip_dto_class = FloatingIp |
1096 | |
1097 | + def floating_ip_count_by_project(self, project_id): |
1098 | + return self._session.query(self.floating_ip_dto_class).\ |
1099 | + filter_by(project_id=project_id).\ |
1100 | + filter_by(deleted=False).\ |
1101 | + count() |
1102 | + |
1103 | def floating_ip_allocate_address(self, host, project_id): |
1104 | - # TODO: Check authorizations much earlier before calling |
1105 | - # this. Doing that in DB layer is way too late. |
1106 | - # nova_api.authorize_project_context(context, project_id) |
1107 | with self._session.begin(): |
1108 | floating_ip_ref = self._session.query(self.floating_ip_dto_class).\ |
1109 | - filter_by(host=host).\ |
1110 | - filter_by(fixed_ip_id=None).\ |
1111 | - filter_by(project_id=None).\ |
1112 | - filter_by(deleted=False).\ |
1113 | - with_lockmode('update').\ |
1114 | - first() |
1115 | + filter_by(host=host).\ |
1116 | + filter_by(fixed_ip_id=None).\ |
1117 | + filter_by(project_id=None).\ |
1118 | + filter_by(deleted=False).\ |
1119 | + with_lockmode('update').\ |
1120 | + first() |
1121 | # NOTE(vish): if with_lockmode isn't supported, as in sqlite, |
1122 | # then this has concurrency issues |
1123 | if not floating_ip_ref: |
1124 | raise nova_db.NoMoreAddresses() |
1125 | floating_ip_ref['project_id'] = project_id |
1126 | self._session.add(floating_ip_ref) |
1127 | - return floating_ip_ref['address'] |
1128 | - |
1129 | - def floating_ip_count_by_project(self, project_id): |
1130 | - # TODO: Check authorizations much earlier before calling |
1131 | - # this. Doing that in DB layer is way too late. |
1132 | - # nova_api.authorize_project_context(context, project_id) |
1133 | - return self._session.query(self.floating_ip_dto_class).\ |
1134 | - filter_by(project_id=project_id).\ |
1135 | - filter_by(deleted=False).\ |
1136 | - count() |
1137 | + return floating_ip_ref |
1138 | |
1139 | def floating_ip_deallocate(self, address): |
1140 | with self._session.begin(): |
1141 | - # TODO(devcamcar): How to ensure floating id belongs to user? |
1142 | - floating_ip_ref = self.floating_ip_get_by_address(address) |
1143 | + floating_ip_ref = self.floating_ip_get_by_address( |
1144 | + address, read_deleted=False) |
1145 | floating_ip_ref['project_id'] = None |
1146 | floating_ip_ref.save(session=self._session) |
1147 | |
1148 | def floating_ip_destroy(self, address): |
1149 | with self._session.begin(): |
1150 | - # TODO(devcamcar): Ensure address belongs to user. |
1151 | - floating_ip_ref = self.floating_ip_get_by_address(address) |
1152 | + floating_ip_ref = self.floating_ip_get_by_address( |
1153 | + address, read_deleted=False) |
1154 | floating_ip_ref.delete(session=self._session) |
1155 | |
1156 | def floating_ip_disassociate_by_address(self, address): |
1157 | with self._session.begin(): |
1158 | - # TODO(devcamcar): Ensure address belongs to user. |
1159 | - # Does get_floating_ip_by_address handle this? |
1160 | - floating_ip_ref = self.floating_ip_get_by_address(address) |
1161 | + floating_ip_ref = self.floating_ip_get_by_address( |
1162 | + address, read_deleted=False) |
1163 | fixed_ip_ref = floating_ip_ref.fixed_ip |
1164 | if fixed_ip_ref: |
1165 | fixed_ip_address = fixed_ip_ref['address'] |
1166 | @@ -387,38 +366,32 @@ |
1167 | return fixed_ip_address |
1168 | |
1169 | def floating_ip_get_all(self): |
1170 | - if not self._is_admin: |
1171 | - raise exception.NotAuthorized() |
1172 | return self._session.query(self.floating_ip_dto_class).\ |
1173 | options(joinedload_all('fixed_ip.ethernet_card')).\ |
1174 | filter_by(deleted=False).\ |
1175 | all() |
1176 | |
1177 | def floating_ip_get_all_by_project(self, project_id): |
1178 | - # TODO: Check authorizations much earlier before calling |
1179 | - # this. Doing that in DB layer is way too late. |
1180 | - # nova_api.authorize_project_context(context, project_id) |
1181 | return self._session.query(self.floating_ip_dto_class).\ |
1182 | options(joinedload_all('fixed_ip.ethernet_card')).\ |
1183 | filter_by(project_id=project_id).\ |
1184 | filter_by(deleted=False).\ |
1185 | all() |
1186 | |
1187 | - def floating_ip_get_by_address(self, address): |
1188 | - # TODO(devcamcar): Ensure the address belongs to user. |
1189 | - result = session.query(self.floating_ip_dto_class).\ |
1190 | + def floating_ip_get_by_address(self, address, read_deleted=False): |
1191 | + result = self._session.query(self.floating_ip_dto_class).\ |
1192 | options(joinedload_all('fixed_ip.network')).\ |
1193 | filter_by(address=address).\ |
1194 | - filter_by(deleted=self._can_read_deleted).\ |
1195 | + filter_by(deleted=read_deleted).\ |
1196 | first() |
1197 | if not result: |
1198 | raise exception.NotFound('No floating ip for address %s' % address) |
1199 | - |
1200 | return result |
1201 | |
1202 | def floating_ip_update(self, address, values): |
1203 | with self._session.begin(): |
1204 | - floating_ip_ref = self.floating_ip_get_by_address(address) |
1205 | + floating_ip_ref = self.floating_ip_get_by_address( |
1206 | + address, read_deleted=False) |
1207 | for (key, value) in values.iteritems(): |
1208 | floating_ip_ref[key] = value |
1209 | floating_ip_ref.save(session=self._session) |
1210 | @@ -431,9 +404,8 @@ |
1211 | |
1212 | def floating_ip_disassociate(self, address): |
1213 | with self._session.begin(): |
1214 | - # TODO(devcamcar): Ensure address belongs to user. |
1215 | - # Does get_floating_ip_by_address handle this? |
1216 | - floating_ip_ref = self.floating_ip_get_by_address(address) |
1217 | + floating_ip_ref = self.floating_ip_get_by_address( |
1218 | + address, read_deleted=False) |
1219 | fixed_ip_ref = floating_ip_ref.fixed_ip |
1220 | if fixed_ip_ref: |
1221 | fixed_ip_address = fixed_ip_ref['address'] |
1222 | @@ -441,11 +413,9 @@ |
1223 | fixed_ip_address = None |
1224 | floating_ip_ref.fixed_ip = None |
1225 | floating_ip_ref.save(session=self._session) |
1226 | - return fixed_ip_address |
1227 | + return fixed_ip_ref |
1228 | |
1229 | def floating_ip_get_all_by_host(self, host): |
1230 | - if not self._is_admin: |
1231 | - raise exception.NotAuthorized() |
1232 | return self._session.query(self.floating_ip_dto_class).\ |
1233 | options(joinedload_all('fixed_ip.ethernet_card')).\ |
1234 | filter_by(host=host).\ |
1235 | @@ -495,8 +465,6 @@ |
1236 | return result |
1237 | |
1238 | def network_get_by_cidr(self, cidr): |
1239 | - if not self._is_admin: |
1240 | - raise exception.NotAuthorized() |
1241 | result = self._session.query(self.network_dto_class).\ |
1242 | filter_by(cidr=cidr).first() |
1243 | |
1244 | @@ -506,8 +474,6 @@ |
1245 | return result |
1246 | |
1247 | def network_associate(self, project_id): |
1248 | - if not self._is_admin: |
1249 | - raise exception.NotAuthorized() |
1250 | with self._session.begin(): |
1251 | network_ref = self._session.query(self.network_dto_class).\ |
1252 | filter_by(deleted=False).\ |
1253 | @@ -522,17 +488,17 @@ |
1254 | self._session.add(network_ref) |
1255 | return network_ref |
1256 | |
1257 | - def fixed_ip_get_network(self, address): |
1258 | - if not self._is_admin: |
1259 | - raise exception.NotAuthorized() |
1260 | - fixed_ip_ref = self.fixed_ip_get_by_address(address) |
1261 | + def fixed_ip_get_network(self, address, read_deleted=False): |
1262 | + fixed_ip_ref = self.fixed_ip_get_by_address( |
1263 | + address, read_deleted=read_deleted) |
1264 | return fixed_ip_ref.network |
1265 | |
1266 | def floating_ip_fixed_ip_associate(self, floating_address, fixed_address): |
1267 | with self._session.begin(): |
1268 | - # TODO(devcamcar): How to ensure floating_id belongs to user? |
1269 | - floating_ip_ref = self.floating_ip_get_by_address(floating_address) |
1270 | - fixed_ip_ref = self.fixed_ip_get_by_address(fixed_address) |
1271 | + floating_ip_ref = self.floating_ip_get_by_address( |
1272 | + floating_address, read_deleted=False) |
1273 | + fixed_ip_ref = self.fixed_ip_get_by_address( |
1274 | + fixed_address, read_deleted=False) |
1275 | floating_ip_ref.fixed_ip = fixed_ip_ref |
1276 | floating_ip_ref.save(session=self._session) |
1277 | |
1278 | @@ -553,8 +519,6 @@ |
1279 | self._session.add(fixed_ip_ref) |
1280 | |
1281 | def fixed_ip_associate_pool(self, network_id, ethernet_card_id): |
1282 | - if not self._is_admin: |
1283 | - raise exception.NotAuthorized() |
1284 | with self._session.begin(): |
1285 | network_or_none = or_( |
1286 | self.fixed_ip_dto_class.network_id == network_id, |
1287 | @@ -572,4 +536,4 @@ |
1288 | ip_ref.network = self.network_get(network_id) |
1289 | ip_ref.ethernet_card = self.ethernet_card_get(ethernet_card_id) |
1290 | self._session.add(ip_ref) |
1291 | - return ip_ref |
1292 | \ No newline at end of file |
1293 | + return ip_ref |
1294 | |
1295 | === modified file 'nova/network/flat_vlan/network.py' |
1296 | --- nova/network/flat_vlan/network.py 2011-04-04 09:52:18 +0000 |
1297 | +++ nova/network/flat_vlan/network.py 2011-04-06 17:14:53 +0000 |
1298 | @@ -32,18 +32,18 @@ |
1299 | LOG = logging.getLogger("nova.net_flat_vlan") |
1300 | LOG_DHCP = logging.getLogger('nova.dhcpbridge-flat-vlan') |
1301 | |
1302 | -DhcpHost = collections.namedtuple('DhcpHost', |
1303 | +DhcpHost = collections.namedtuple('DhcpHost', |
1304 | 'mac_address, hostname, ip_address, timestamp') |
1305 | |
1306 | class NetworkService(nova_manager.SchedulerDependentManager): |
1307 | |
1308 | - timeout_fixed_ips = (FLAGS.net_flat_vlan_use_vlan or |
1309 | + timeout_fixed_ips = (FLAGS.net_flat_vlan_use_vlan or |
1310 | FLAGS.net_flat_vlan_use_dhcp) |
1311 | |
1312 | def __init__(self, network_driver=None, dhcp_driver=None, ra_driver=None, |
1313 | filter_driver=None, *args, **kwargs): |
1314 | """Initializes vlan network service. |
1315 | - |
1316 | + |
1317 | Args: |
1318 | network_driver: The network driver for the OS. |
1319 | dhcp_driver: The DHCP driver to use for DHCP service. |
1320 | @@ -57,8 +57,8 @@ |
1321 | ra_driver = FLAGS.net_flat_vlan_ra_driver |
1322 | if not filter_driver: |
1323 | filter_driver = FLAGS.net_flat_vlan_filter_driver |
1324 | - |
1325 | - kwargs['db_driver'] = 'nova.network.flat_vlan.db.api' |
1326 | + |
1327 | + kwargs['db_driver'] = 'nova.network.flat_vlan.db.api' |
1328 | self.driver = utils.import_object(network_driver) |
1329 | self.dhcp_driver = utils.import_object(dhcp_driver) |
1330 | self.ra_driver = utils.import_object(ra_driver) |
1331 | @@ -86,13 +86,14 @@ |
1332 | # NOTE(vish): The False here is because we ignore the case |
1333 | # that the ip is already bound. |
1334 | self.driver.bind_floating_ip(floating_ip['address'], False) |
1335 | - self.driver.ensure_floating_forward(floating_ip['address'], |
1336 | - fixed_address) |
1337 | - self.filter_driver.metadata_forward() |
1338 | + self.filter_driver.ensure_floating_forward( |
1339 | + floating_ip['address'], fixed_address) |
1340 | + |
1341 | + self.filter_driver.metadata_forward() |
1342 | |
1343 | def periodic_tasks(self, context=None): |
1344 | """Tasks to be run at a periodic interval. |
1345 | - |
1346 | + |
1347 | Args: |
1348 | context: Nova context |
1349 | """ |
1350 | @@ -109,7 +110,7 @@ |
1351 | |
1352 | def _set_vlan_host(self, context, network_id): |
1353 | """Sets up VLAN networking service host. |
1354 | - |
1355 | + |
1356 | Args: |
1357 | context: Nova context |
1358 | network_id: ID of the network |
1359 | @@ -136,11 +137,11 @@ |
1360 | network_ref['vpn_private_address']) |
1361 | |
1362 | if not FLAGS.fake_network: |
1363 | - hosts = self._get_dhcp_hosts(context, network_id) |
1364 | + hosts = self._get_dhcp_hosts(context, network_id) |
1365 | bridge = network_ref['bridge'] |
1366 | - self.dhcp_driver.update_dhcp(bridge, |
1367 | - network_ref['gateway'], |
1368 | - network_ref['dhcp_start'], |
1369 | + self.dhcp_driver.update_dhcp(bridge, |
1370 | + network_ref['gateway'], |
1371 | + network_ref['dhcp_start'], |
1372 | hosts, |
1373 | dhcp_script=FLAGS.net_flat_vlan_dhcpbridge) |
1374 | if(FLAGS.net_flat_vlan_use_ipv6): |
1375 | @@ -148,11 +149,11 @@ |
1376 | network_ref['cidr_v6']) |
1377 | self.db.network_update(context, network_id, |
1378 | {"gateway_v6": |
1379 | - utils.get_my_linklocal(bridge)}) |
1380 | + utils.get_my_linklocal(bridge)}) |
1381 | |
1382 | def _set_dhcp_host(self, context, network_id): |
1383 | """Sets up DHCP(no VLAN) networking service host. |
1384 | - |
1385 | + |
1386 | Args: |
1387 | context: Nova context |
1388 | network_id: ID of the network |
1389 | @@ -171,22 +172,22 @@ |
1390 | |
1391 | if not FLAGS.fake_network: |
1392 | hosts = self._get_dhcp_hosts(context, network_id) |
1393 | - self.dhcp_driver.update_dhcp(bridge, |
1394 | - network_ref['gateway'], |
1395 | - network_ref['dhcp_start'], |
1396 | + self.dhcp_driver.update_dhcp(bridge, |
1397 | + network_ref['gateway'], |
1398 | + network_ref['dhcp_start'], |
1399 | hosts, |
1400 | dhcp_script=FLAGS.net_flat_vlan_dhcpbridge) |
1401 | - |
1402 | + |
1403 | if(FLAGS.net_flat_vlan_use_ipv6): |
1404 | self.ra_driver.update_ra(bridge, |
1405 | network_ref['cidr_v6']) |
1406 | self.db.network_update(context, network_id, |
1407 | {"gateway_v6": |
1408 | - utils.get_my_linklocal(bridge)}) |
1409 | - |
1410 | + utils.get_my_linklocal(bridge)}) |
1411 | + |
1412 | def set_network_host(self, context, network_id): |
1413 | """Called when this host becomes the host for a network. |
1414 | - |
1415 | + |
1416 | Args: |
1417 | context: Nova context to access DB. |
1418 | network_id: ID of the network |
1419 | @@ -201,11 +202,11 @@ |
1420 | net['host'] = self.host |
1421 | self.db.network_update(context, network_id, net) |
1422 | |
1423 | - return self.host |
1424 | - |
1425 | + return self.host |
1426 | + |
1427 | def _get_dhcp_hosts(self, context, network_id): |
1428 | """Get a list containing a network's hosts |
1429 | - |
1430 | + |
1431 | Args: |
1432 | context: Nova context |
1433 | network_id: Network ID to get the DHCP hosts for. |
1434 | @@ -224,10 +225,10 @@ |
1435 | ip_address=fixed_ip_ref['address'], |
1436 | timestamp=None)) |
1437 | return hosts |
1438 | - |
1439 | + |
1440 | def allocate_fixed_ips(self, context, vnic_ids, is_vpn): |
1441 | """Gets a fixed ip from the pool. |
1442 | - |
1443 | + |
1444 | Args: |
1445 | context: Nova context needed to access DB. |
1446 | vnic_ids: List of VNIC IDs. |
1447 | @@ -236,29 +237,29 @@ |
1448 | for vnic_id in vnic_ids: |
1449 | if FLAGS.net_flat_vlan_use_vlan: |
1450 | ip_address = manager.bind_ip_to_ethernet_card_by_project( |
1451 | - context, |
1452 | + context, |
1453 | vnic_id, |
1454 | is_vpn) |
1455 | else: |
1456 | ip_address = manager.bind_ip_to_ethernet_card_by_bridge( |
1457 | - context, |
1458 | - vnic_id) |
1459 | + context, |
1460 | + vnic_id) |
1461 | |
1462 | if not FLAGS.fake_network and (FLAGS.net_flat_vlan_use_vlan or |
1463 | FLAGS.net_flat_vlan_use_dhcp): |
1464 | network_id = ip_address['network_id'] |
1465 | network_ref = self.db.network_get(context, network_id) |
1466 | - hosts = self._get_dhcp_hosts(context, network_id) |
1467 | - self.dhcp_driver.update_dhcp(network_ref['bridge'], |
1468 | + hosts = self._get_dhcp_hosts(context, network_id) |
1469 | + self.dhcp_driver.update_dhcp(network_ref['bridge'], |
1470 | network_ref['gateway'], |
1471 | network_ref['dhcp_start'], |
1472 | - hosts, |
1473 | + hosts, |
1474 | dhcp_script=FLAGS.net_flat_vlan_dhcpbridge) |
1475 | |
1476 | |
1477 | def lease_fixed_ip(self, context, mac, address): |
1478 | """Called by dhcp-bridge when ip is leased. |
1479 | - |
1480 | + |
1481 | Args: |
1482 | context: Nova context |
1483 | mac: MAC address to lease the IP address against. |
1484 | @@ -267,19 +268,19 @@ |
1485 | LOG.debug(_("Leasing IP %s"), address, context=context) |
1486 | fixed_ip_ref = self.db.fixed_ip_get_by_address(context, address) |
1487 | ethernet_card = fixed_ip_ref['ethernet_card'] |
1488 | - instance = nova_db_api.instance_get_by_virtual_nic(context, |
1489 | + instance = nova_db_api.instance_get_by_virtual_nic(context, |
1490 | ethernet_card['id']) |
1491 | if not instance: |
1492 | raise exception.Error(_("IP %s leased that isn't associated") % |
1493 | address) |
1494 | - |
1495 | + |
1496 | if nova_db_api.is_user_context(context): |
1497 | # Get the project for this IP |
1498 | nova_db_api.authorize_project_context(context, instance.project_id) |
1499 | - |
1500 | + |
1501 | if ethernet_card['mac_address'] != mac: |
1502 | raise exception.Error(_("IP %(address)s leased to bad" |
1503 | - " mac %s vs %s") % (ethernet_card['mac_address'], mac)) |
1504 | + " mac %s vs %s") % (ethernet_card['mac_address'], mac)) |
1505 | now = datetime.datetime.utcnow() |
1506 | self.db.fixed_ip_update(context, |
1507 | fixed_ip_ref['id'], |
1508 | @@ -288,13 +289,13 @@ |
1509 | if not fixed_ip_ref['allocated']: |
1510 | LOG.warn(_("IP %s leased that was already deallocated"), address, |
1511 | context=context) |
1512 | - |
1513 | + |
1514 | def get_dhcp_host_leases(self, context, interface): |
1515 | """Gets a list of leased hosts. |
1516 | - |
1517 | + |
1518 | Args: |
1519 | context: Nova context |
1520 | - interface: network interface to get the DHCP leases. |
1521 | + interface: network interface to get the DHCP leases. |
1522 | """ |
1523 | network_ref = self.db.network_get_by_bridge(context, interface) |
1524 | hosts = [] |
1525 | @@ -305,21 +306,21 @@ |
1526 | instance = nova_db_api.\ |
1527 | instance_get_by_virtual_nic(context, |
1528 | ethernet_card['id']) |
1529 | - |
1530 | + |
1531 | if instance['updated_at']: |
1532 | timestamp = instance['updated_at'] |
1533 | else: |
1534 | timestamp = instance['created_at'] |
1535 | - |
1536 | + |
1537 | hosts.append(DhcpHost(mac_address=ethernet_card['mac_address'], |
1538 | hostname=instance['hostname'], |
1539 | ip_address=fixed_ip_ref['address'], |
1540 | timestamp=timestamp)) |
1541 | return self.dhcp_driver.get_dhcp_leases(hosts) |
1542 | - |
1543 | + |
1544 | def release_fixed_ip(self, context, mac, address): |
1545 | """Called by dhcp-bridge when ip is released. |
1546 | - |
1547 | + |
1548 | Args: |
1549 | context: Nova context |
1550 | mac: MAC address to release the IP against. |
1551 | @@ -328,7 +329,7 @@ |
1552 | LOG.debug(_("Releasing IP %s"), address, context=context) |
1553 | fixed_ip_ref = self.db.fixed_ip_get_by_address(context, address) |
1554 | ethernet_card = fixed_ip_ref['ethernet_card'] |
1555 | - instance = nova_db_api.instance_get_by_virtual_nic(context, |
1556 | + instance = nova_db_api.instance_get_by_virtual_nic(context, |
1557 | ethernet_card['id']) |
1558 | if not instance: |
1559 | raise exception.Error(_("IP %s released that isn't associated") % |
1560 | @@ -340,7 +341,7 @@ |
1561 | |
1562 | if ethernet_card['mac_address'] != mac: |
1563 | raise exception.Error(_("IP %(address)s leased to bad" |
1564 | - " mac %s vs %s") % (ethernet_card['mac_address'], mac)) |
1565 | + " mac %s vs %s") % (ethernet_card['mac_address'], mac)) |
1566 | |
1567 | if not fixed_ip_ref['leased']: |
1568 | LOG.warn(_("IP %s released that was not leased"), address, |
1569 | @@ -355,25 +356,45 @@ |
1570 | # the code below will update the file if necessary |
1571 | if FLAGS.net_flat_vlan_update_dhcp_on_disassociate: |
1572 | network_ref = fixed_ip['network'] |
1573 | - hosts = self._get_dhcp_hosts(context, network_ref['id']) |
1574 | - self.dhcp_driver.update_dhcp(network_ref['bridge'], |
1575 | - network_ref['gateway'], |
1576 | - network_ref['dhcp_start'], |
1577 | + hosts = self._get_dhcp_hosts(context, network_ref['id']) |
1578 | + self.dhcp_driver.update_dhcp(network_ref['bridge'], |
1579 | + network_ref['gateway'], |
1580 | + network_ref['dhcp_start'], |
1581 | hosts, |
1582 | dhcp_script=FLAGS.\ |
1583 | net_flat_vlan_dhcpbridge) |
1584 | |
1585 | - def disassociate_floating_ip(self, context, floating_address): |
1586 | - """Disassociates a floating ip. |
1587 | - |
1588 | - Args: |
1589 | - context: Nova context |
1590 | - floating_address: Floating IP address to diassociate. |
1591 | - """ |
1592 | - fixed_address = self.db.floating_ip_disassociate(context, |
1593 | - floating_address) |
1594 | + def get_host(self, context): |
1595 | + """Gets the host of the network service. |
1596 | + |
1597 | + Args: |
1598 | + context: Nova context object. Unused here. |
1599 | + """ |
1600 | + return self.host |
1601 | + |
1602 | + def activate_public_ip(self, context, floating_address, fixed_address): |
1603 | + """Associates an floating ip to a fixed ip. |
1604 | + |
1605 | + Args: |
1606 | + context: Nova context |
1607 | + floating_address: Floating IP address to map to fixed IP address. |
1608 | + fixed_address: Fixed IP address to map the floating IP address to. |
1609 | + """ |
1610 | + self.driver.bind_floating_ip(floating_address) |
1611 | + self.filter_driver.ensure_floating_forward(floating_address, |
1612 | + fixed_address) |
1613 | + |
1614 | + def deactivate_public_ip(self, context, floating_address, fixed_address): |
1615 | + """Disassociates floating address and fixed address. |
1616 | + |
1617 | + Args: |
1618 | + context: Nova context |
1619 | + floating_address: Floating IP address to map to fixed IP address. |
1620 | + fixed_address: Fixed IP address to map the floating IP address to. |
1621 | + """ |
1622 | self.driver.unbind_floating_ip(floating_address) |
1623 | - self.driver.remove_floating_forward(floating_address, fixed_address) |
1624 | + self.filter_driver.remove_floating_forward(floating_address, |
1625 | + fixed_address) |
1626 | |
1627 | |
1628 | class DHCPEventHandler(object): |
1629 | @@ -388,7 +409,7 @@ |
1630 | return NetworkService().get_dhcp_host_leases(ctxt, interface) |
1631 | else: |
1632 | return rpc.cast(ctxt, |
1633 | - "%s.%s" % (FLAGS.net_flat_vlan_network_topic, |
1634 | + "%s.%s" % (FLAGS.net_flat_vlan_network_topic, |
1635 | FLAGS.host), |
1636 | {"method": "get_dhcp_host_leases", |
1637 | "args": {"interface": interface}}) |
1638 | @@ -402,7 +423,7 @@ |
1639 | return NetworkService().lease_fixed_ip(ctxt, mac, ip_address) |
1640 | else: |
1641 | rpc.cast(ctxt, |
1642 | - "%s.%s" % (FLAGS.net_flat_vlan_network_topic, |
1643 | + "%s.%s" % (FLAGS.net_flat_vlan_network_topic, |
1644 | FLAGS.host), |
1645 | {"method": "lease_fixed_ip", |
1646 | "args": {"mac": mac, |
1647 | @@ -423,9 +444,9 @@ |
1648 | NetworkService().release_fixed_ip(ctxt, mac, ip_address) |
1649 | else: |
1650 | rpc.cast(ctxt, |
1651 | - "%s.%s" % (FLAGS.net_flat_vlan_network_topic, |
1652 | + "%s.%s" % (FLAGS.net_flat_vlan_network_topic, |
1653 | FLAGS.host), |
1654 | {"method": "release_fixed_ip", |
1655 | "args": {"mac": mac, |
1656 | "address": ip_address}}) |
1657 | - |
1658 | + |
1659 | |
1660 | === modified file 'nova/network/service.py' |
1661 | --- nova/network/service.py 2011-04-04 09:52:18 +0000 |
1662 | +++ nova/network/service.py 2011-04-06 17:14:53 +0000 |
1663 | @@ -19,14 +19,14 @@ |
1664 | service management.""" |
1665 | |
1666 | from nova import db |
1667 | -from nova import flags |
1668 | +from nova import flags |
1669 | from nova import utils |
1670 | |
1671 | from zope import interface |
1672 | |
1673 | # Flag definitions |
1674 | FLAGS = flags.FLAGS |
1675 | -flags.DEFINE_string('network_service_conf', |
1676 | +flags.DEFINE_string('network_service_conf', |
1677 | '/etc/nova/nova-network-service.conf', |
1678 | 'Path to the network service configuration file.') |
1679 | flags.DEFINE_string('default_network_service', 'nova.network.flat_vlan', |
1680 | @@ -37,102 +37,117 @@ |
1681 | |
1682 | def get_net_agent(): |
1683 | """Gets the Net agent service object. |
1684 | - |
1685 | + |
1686 | Returns: |
1687 | Net agent object. |
1688 | """ |
1689 | - |
1690 | + |
1691 | def get_api_service(): |
1692 | """Gets the API service object. |
1693 | - |
1694 | + |
1695 | Returns: |
1696 | Network API service object. |
1697 | """ |
1698 | - |
1699 | + |
1700 | def get_os_api_service(): |
1701 | """Gets the OpenStack API service object. |
1702 | - |
1703 | + |
1704 | Returns: |
1705 | Network OpenStack API service object. |
1706 | """ |
1707 | |
1708 | class INetworkApiService(interface.Interface): |
1709 | """A Network API service object.""" |
1710 | - |
1711 | + |
1712 | def create_vnic(): |
1713 | """Creates a new VNIC. |
1714 | - |
1715 | + |
1716 | Returns: |
1717 | The ID of the new VNIC. |
1718 | """ |
1719 | - |
1720 | + |
1721 | def get_project_vpn_address_and_port(context, project_id): |
1722 | """Gets the VPN IP address and port for a project |
1723 | - |
1724 | + |
1725 | Args: |
1726 | context: Nova context object needed to access DB. |
1727 | project_id: Project to get the VPN IP and port for. |
1728 | - |
1729 | + |
1730 | Returns: |
1731 | A tuple of VPN IP address and port number. |
1732 | """ |
1733 | |
1734 | + def allocate_address(context, project_id, ip_quota): |
1735 | + """Gets the number of floating IPs associated with a project. |
1736 | + |
1737 | + Args: |
1738 | + context: Nova context object needed to access the DB. |
1739 | + project_id: Project to allocate the address from. |
1740 | + ip_quota: Quota for IP addresses. |
1741 | + |
1742 | + Returns: |
1743 | + An IP address. |
1744 | + |
1745 | + Raises: |
1746 | + quota.QuotaError: Over the quota limit. |
1747 | + """ |
1748 | + |
1749 | class INetworkOpenStackApiService(interface.Interface): |
1750 | """An OpenStack Network API service object.""" |
1751 | - |
1752 | + |
1753 | def set_routes(route_map): |
1754 | """Set necessary routes for the plugin. |
1755 | - |
1756 | + |
1757 | Args: |
1758 | route_map: NetworkServiceRouteMap object to add the routes to. |
1759 | - """ |
1760 | + """ |
1761 | |
1762 | class INetworkAgentService(interface.Interface): |
1763 | """An OpenStack network agent service object.""" |
1764 | - |
1765 | + |
1766 | def bind_vnics_to_ports(context, vnic_ids, is_vpn): |
1767 | """Gets a fixed ips from the pool. |
1768 | - |
1769 | + |
1770 | Args: |
1771 | context: Nova context needed for DB access. |
1772 | vnic_ids: list of VNIC IDs |
1773 | - is_vpn: Boolean to check if the call is for VPN. |
1774 | + is_vpn: Boolean to check if the call is for VPN. |
1775 | """ |
1776 | - |
1777 | + |
1778 | def setup_compute_network(context, vnic_ids, is_vpn): |
1779 | """Set up the compute node for networking. |
1780 | - |
1781 | + |
1782 | Args: |
1783 | context: Nova context needed for DB access. |
1784 | vnic_ids: list of VNIC IDs |
1785 | is_vpn: Boolean to check if the call is for VPN. |
1786 | """ |
1787 | - |
1788 | + |
1789 | def teardown_compute_network(context, vnic_ids): |
1790 | """Clean up the compute node. |
1791 | - |
1792 | + |
1793 | Args: |
1794 | context: Nova context needed for DB access. |
1795 | vnic_ids: list of VNIC IDs |
1796 | """ |
1797 | - |
1798 | + |
1799 | def requires_file_injection(): |
1800 | """Indicates whether the plugin requires file injection. |
1801 | - |
1802 | + |
1803 | Returns: |
1804 | True if the plugin requires file injection. |
1805 | """ |
1806 | - |
1807 | + |
1808 | def get_network_info(context, vnic_id): |
1809 | """Gets network data for a given VNIC. |
1810 | - |
1811 | + |
1812 | Args: |
1813 | context: Nova context needed for DB access. |
1814 | vnic_id: VNIC ID to get the network information for. |
1815 | - |
1816 | + |
1817 | Returns: |
1818 | A dictionary containing the following keys: |
1819 | - cidr, cidrv6, netmask, netmask_v6 gateway, gateway_v6, |
1820 | + cidr, cidrv6, netmask, netmask_v6 gateway, gateway_v6, |
1821 | dhcp_server, broadcast, dns, mac_address, |
1822 | ip_address, bridge, gateway_v6, and netmast_v6 |
1823 | """ |
1824 | @@ -142,7 +157,7 @@ |
1825 | |
1826 | def __init__(self, mapper, service): |
1827 | """Initialize a NetworkServiceRouteMap object. |
1828 | - |
1829 | + |
1830 | Args: |
1831 | mapper: python-routes mapper object to wrap. |
1832 | service: module of the network plugin service. |
1833 | @@ -152,34 +167,34 @@ |
1834 | |
1835 | def resource(self, member_name, collection_name, **kwargs): |
1836 | """Wrapper method for 'resource' method in python-routes mapper object. |
1837 | - |
1838 | + |
1839 | This method does the same thing 'resource' method does for python-routes |
1840 | - module, but it also adds a route prefix from the network service name. |
1841 | - |
1842 | + module, but it also adds a route prefix from the network service name. |
1843 | + |
1844 | Args: |
1845 | member_name: REST member routes |
1846 | collection_name: REST collection routes |
1847 | """ |
1848 | _, _, package_name = str(self._service.__package__).rpartition('.') |
1849 | kwargs.pop('path_prefix', None) |
1850 | - self._mapper.resource(member_name, collection_name, |
1851 | + self._mapper.resource(member_name, collection_name, |
1852 | path_prefix='/%s' % package_name, **kwargs) |
1853 | |
1854 | class NetworkServiceManager(object): |
1855 | - """Implements Borg design pattern to have a shared state of network |
1856 | + """Implements Borg design pattern to have a shared state of network |
1857 | services. |
1858 | """ |
1859 | |
1860 | __shared_state = {} |
1861 | _services = {} |
1862 | - |
1863 | + |
1864 | def __init__(self): |
1865 | """Initialize services member dictionary variable. |
1866 | """ |
1867 | self.__dict__ = self.__shared_state |
1868 | |
1869 | def _import_services(self): |
1870 | - """Loads the content of the configuration file and imports the |
1871 | + """Loads the content of the configuration file and imports the |
1872 | modules. |
1873 | """ |
1874 | self._services = {} |
1875 | @@ -190,11 +205,11 @@ |
1876 | continue |
1877 | self._services[line] = utils.import_object(line) |
1878 | f.close() |
1879 | - |
1880 | + |
1881 | @property |
1882 | def _services_dict(self): |
1883 | """Gets the services dictionary. Loads the services if empty. |
1884 | - |
1885 | + |
1886 | Returns: |
1887 | A dictionary of service name to service modules. |
1888 | """ |
1889 | @@ -205,11 +220,11 @@ |
1890 | @classmethod |
1891 | def get_service_name(cls, context, project_id): |
1892 | """Gets the network service given a project ID. |
1893 | - |
1894 | + |
1895 | Args: |
1896 | context: Nova context object needed for DB access. |
1897 | project_id: Project ID to get the service of. |
1898 | - |
1899 | + |
1900 | Returns: |
1901 | Network service name for the project. |
1902 | """ |
1903 | @@ -220,20 +235,20 @@ |
1904 | |
1905 | def get_service(self, context, project_id): |
1906 | """Gets the network service given a project ID. |
1907 | - |
1908 | + |
1909 | Args: |
1910 | context: Nova context object needed for DB access. |
1911 | project_id: Project ID to get the service of. |
1912 | - |
1913 | + |
1914 | Returns: |
1915 | Network service module for the project. |
1916 | """ |
1917 | service = self.get_service_name(context, project_id) |
1918 | return self._services_dict[service] |
1919 | - |
1920 | + |
1921 | def get_all_services(self): |
1922 | """Gets all the network services available. |
1923 | - |
1924 | + |
1925 | Returns: |
1926 | Network service modules available. |
1927 | """ |
1928 | @@ -241,21 +256,21 @@ |
1929 | |
1930 | def get_service_factory(context, project_id): |
1931 | """Gets the factory object for network service. |
1932 | - |
1933 | + |
1934 | Args: |
1935 | context: Nova context needed for accessing DB. |
1936 | project_id: Project ID to get the appropriate network service. |
1937 | - |
1938 | + |
1939 | Returns: |
1940 | A tuple of the service module and its NetworkServiceFactory object. |
1941 | """ |
1942 | manager = NetworkServiceManager() |
1943 | service = manager.get_service(context, project_id) |
1944 | return (service, service.NetworkServiceFactory()) |
1945 | - |
1946 | + |
1947 | def get_all_service_factories(): |
1948 | """Gets all the factory objects for network services. |
1949 | - |
1950 | + |
1951 | Returns: |
1952 | A list of tuples of service module and its factory. |
1953 | """ |
1954 | |
1955 | === modified file 'nova/virt/libvirt_conn.py' |
1956 | --- nova/virt/libvirt_conn.py 2011-04-04 09:52:18 +0000 |
1957 | +++ nova/virt/libvirt_conn.py 2011-04-06 17:14:53 +0000 |
1958 | @@ -238,10 +238,7 @@ |
1959 | |
1960 | vnics = db.virtual_nics_get_by_instance(ctxt, instance['id']) |
1961 | for vnic_id in vnics: |
1962 | - try: |
1963 | - self.firewall_driver.prepare_vnic_filter(vnic_id, instance) |
1964 | - except: |
1965 | - pass |
1966 | + self.firewall_driver.prepare_vnic_filter(vnic_id, instance) |
1967 | |
1968 | def _get_connection(self): |
1969 | if not self._wrapped_conn or not self._test_connection(): |