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