1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright (c) 2011 X.commerce, a business unit of eBay Inc.
4
# Copyright 2010 United States Government as represented by the
5
# Administrator of the National Aeronautics and Space Administration.
8
# Licensed under the Apache License, Version 2.0 (the "License"); you may
9
# not use this file except in compliance with the License. You may obtain
10
# a copy of the License at
12
# http://www.apache.org/licenses/LICENSE-2.0
14
# Unless required by applicable law or agreed to in writing, software
15
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
# License for the specific language governing permissions and limitations
20
This version of the api is deprecated in Grizzly and will be removed.
22
It is provided just in case a third party manager is in use.
28
from nova.db import base
29
from nova import exception
30
from nova.network import model as network_model
31
from nova.network import rpcapi as network_rpcapi
32
from nova.openstack.common import log as logging
33
from nova import policy
35
LOG = logging.getLogger(__name__)
40
Decorator to update the instance_info_cache
42
Requires context and instance as function args
44
argspec = inspect.getargspec(f)
47
def wrapper(self, context, *args, **kwargs):
48
res = f(self, context, *args, **kwargs)
51
# get the instance from arguments (or raise ValueError)
52
instance = kwargs.get('instance')
54
instance = args[argspec.args.index('instance') - 2]
56
msg = _('instance is a required argument to use @refresh_cache')
59
update_instance_cache_with_nw_info(self, context, instance,
62
# return the original function's return value
67
def update_instance_cache_with_nw_info(api, context, instance,
71
if not isinstance(nw_info, network_model.NetworkInfo):
74
nw_info = api._get_instance_nw_info(context, instance)
76
cache = {'network_info': nw_info.json()}
77
api.db.instance_info_cache_update(context, instance['uuid'], cache)
79
LOG.exception(_('Failed storing info cache'), instance=instance)
82
def wrap_check_policy(func):
83
"""Check policy corresponding to the wrapped methods prior to execution."""
85
@functools.wraps(func)
86
def wrapped(self, context, *args, **kwargs):
87
action = func.__name__
88
check_policy(context, action)
89
return func(self, context, *args, **kwargs)
94
def check_policy(context, action):
96
'project_id': context.project_id,
97
'user_id': context.user_id,
99
_action = 'network:%s' % action
100
policy.enforce(context, _action, target)
103
class API(base.Base):
104
"""API for doing networking via the nova-network network manager.
106
This is a pluggable module - other implementations do networking via
107
other services (such as Quantum).
112
def __init__(self, **kwargs):
113
self.network_rpcapi = network_rpcapi.NetworkAPI()
114
super(API, self).__init__(**kwargs)
117
def get_all(self, context):
118
return self.network_rpcapi.get_all_networks(context)
121
def get(self, context, network_uuid):
122
return self.network_rpcapi.get_network(context, network_uuid)
125
def create(self, context, **kwargs):
126
return self.network_rpcapi.create_networks(context, **kwargs)
129
def delete(self, context, network_uuid):
130
return self.network_rpcapi.delete_network(context, network_uuid, None)
133
def disassociate(self, context, network_uuid):
134
return self.network_rpcapi.disassociate_network(context, network_uuid)
137
def get_fixed_ip(self, context, id):
138
return self.network_rpcapi.get_fixed_ip(context, id)
141
def get_fixed_ip_by_address(self, context, address):
142
return self.network_rpcapi.get_fixed_ip_by_address(context, address)
145
def get_floating_ip(self, context, id):
146
return self.network_rpcapi.get_floating_ip(context, id)
149
def get_floating_ip_pools(self, context):
150
return self.network_rpcapi.get_floating_ip_pools(context)
153
def get_floating_ip_by_address(self, context, address):
154
return self.network_rpcapi.get_floating_ip_by_address(context, address)
157
def get_floating_ips_by_project(self, context):
158
return self.network_rpcapi.get_floating_ips_by_project(context)
161
def get_floating_ips_by_fixed_address(self, context, fixed_address):
162
return self.network_rpcapi.get_floating_ips_by_fixed_address(context,
166
def get_backdoor_port(self, context, host):
167
return self.network_rpcapi.get_backdoor_port(context, host)
170
def get_instance_id_by_floating_address(self, context, address):
171
# NOTE(tr3buchet): i hate this
172
return self.network_rpcapi.get_instance_id_by_floating_address(context,
176
def get_vifs_by_instance(self, context, instance):
177
return self.network_rpcapi.get_vifs_by_instance(context,
181
def get_vif_by_mac_address(self, context, mac_address):
182
return self.network_rpcapi.get_vif_by_mac_address(context, mac_address)
185
def allocate_floating_ip(self, context, pool=None):
186
"""Adds (allocates) a floating ip to a project from a pool."""
187
# NOTE(vish): We don't know which network host should get the ip
188
# when we allocate, so just send it to any one. This
189
# will probably need to move into a network supervisor
191
return self.network_rpcapi.allocate_floating_ip(context,
192
context.project_id, pool, False)
195
def release_floating_ip(self, context, address,
196
affect_auto_assigned=False):
197
"""Removes (deallocates) a floating ip with address from a project."""
198
return self.network_rpcapi.deallocate_floating_ip(context, address,
199
affect_auto_assigned)
203
def associate_floating_ip(self, context, instance,
204
floating_address, fixed_address,
205
affect_auto_assigned=False):
206
"""Associates a floating ip with a fixed ip.
208
ensures floating ip is allocated to the project in context
210
orig_instance_uuid = self.network_rpcapi.associate_floating_ip(context,
211
floating_address, fixed_address, affect_auto_assigned)
213
if orig_instance_uuid:
214
msg_dict = dict(address=floating_address,
215
instance_id=orig_instance_uuid)
216
LOG.info(_('re-assign floating IP %(address)s from '
217
'instance %(instance_id)s') % msg_dict)
218
orig_instance = self.db.instance_get_by_uuid(context,
221
# purge cached nw info for the original instance
222
update_instance_cache_with_nw_info(self, context, orig_instance)
226
def disassociate_floating_ip(self, context, instance, address,
227
affect_auto_assigned=False):
228
"""Disassociates a floating ip from fixed ip it is associated with."""
229
self.network_rpcapi.disassociate_floating_ip(context, address,
230
affect_auto_assigned)
234
def allocate_for_instance(self, context, instance, vpn,
235
requested_networks, macs=None):
236
"""Allocates all network structures for an instance.
238
TODO(someone): document the rest of these parameters.
240
:param macs: None or a set of MAC addresses that the instance
241
should use. macs is supplied by the hypervisor driver (contrast
242
with requested_networks which is user supplied).
243
NB: macs is ignored by nova-network.
244
:returns: network info as from get_instance_nw_info() below
248
args['requested_networks'] = requested_networks
249
args['instance_id'] = instance['id']
250
args['instance_uuid'] = instance['uuid']
251
args['project_id'] = instance['project_id']
252
args['host'] = instance['host']
253
args['rxtx_factor'] = instance['instance_type']['rxtx_factor']
254
nw_info = self.network_rpcapi.allocate_for_instance(context, **args)
256
return network_model.NetworkInfo.hydrate(nw_info)
259
def deallocate_for_instance(self, context, instance):
260
"""Deallocates all network structures related to instance."""
263
args['instance_id'] = instance['id']
264
args['project_id'] = instance['project_id']
265
args['host'] = instance['host']
266
self.network_rpcapi.deallocate_for_instance(context, **args)
270
def add_fixed_ip_to_instance(self, context, instance, network_id):
271
"""Adds a fixed ip to instance from specified network."""
272
args = {'instance_id': instance['uuid'],
273
'host': instance['host'],
274
'network_id': network_id}
275
self.network_rpcapi.add_fixed_ip_to_instance(context, **args)
279
def remove_fixed_ip_from_instance(self, context, instance, address):
280
"""Removes a fixed ip from instance from specified network."""
282
args = {'instance_id': instance['uuid'],
283
'host': instance['host'],
285
self.network_rpcapi.remove_fixed_ip_from_instance(context, **args)
288
def add_network_to_project(self, context, project_id, network_uuid=None):
289
"""Force adds another network to a project."""
290
self.network_rpcapi.add_network_to_project(context, project_id,
294
def associate(self, context, network_uuid, host=_sentinel,
296
"""Associate or disassociate host or project to network."""
298
if host is not API._sentinel:
299
associations['host'] = host
300
if project is not API._sentinel:
301
associations['project'] = project
302
self.network_rpcapi.associate(context, network_uuid, associations)
305
def get_instance_nw_info(self, context, instance, update_cache=True):
306
"""Returns all network info related to an instance."""
307
result = self._get_instance_nw_info(context, instance)
309
update_instance_cache_with_nw_info(self, context, instance,
313
def _get_instance_nw_info(self, context, instance):
314
"""Returns all network info related to an instance."""
315
args = {'instance_id': instance['id'],
316
'instance_uuid': instance['uuid'],
317
'rxtx_factor': instance['instance_type']['rxtx_factor'],
318
'host': instance['host'],
319
'project_id': instance['project_id']}
320
nw_info = self.network_rpcapi.get_instance_nw_info(context, **args)
322
return network_model.NetworkInfo.hydrate(nw_info)
325
def validate_networks(self, context, requested_networks):
326
"""validate the networks passed at the time of creating
329
return self.network_rpcapi.validate_networks(context,
333
def get_instance_uuids_by_ip_filter(self, context, filters):
334
"""Returns a list of dicts in the form of
335
{'instance_uuid': uuid, 'ip': ip} that matched the ip_filter
337
return self.network_rpcapi.get_instance_uuids_by_ip_filter(context,
341
def get_dns_domains(self, context):
342
"""Returns a list of available dns domains.
343
These can be used to create DNS entries for floating ips.
345
return self.network_rpcapi.get_dns_domains(context)
348
def add_dns_entry(self, context, address, name, dns_type, domain):
349
"""Create specified DNS entry for address."""
350
args = {'address': address,
352
'dns_type': dns_type,
354
return self.network_rpcapi.add_dns_entry(context, **args)
357
def modify_dns_entry(self, context, name, address, domain):
358
"""Create specified DNS entry for address."""
359
args = {'address': address,
362
return self.network_rpcapi.modify_dns_entry(context, **args)
365
def delete_dns_entry(self, context, name, domain):
366
"""Delete the specified dns entry."""
367
args = {'name': name, 'domain': domain}
368
return self.network_rpcapi.delete_dns_entry(context, **args)
371
def delete_dns_domain(self, context, domain):
372
"""Delete the specified dns domain."""
373
return self.network_rpcapi.delete_dns_domain(context, domain=domain)
376
def get_dns_entries_by_address(self, context, address, domain):
377
"""Get entries for address and domain."""
378
args = {'address': address, 'domain': domain}
379
return self.network_rpcapi.get_dns_entries_by_address(context, **args)
382
def get_dns_entries_by_name(self, context, name, domain):
383
"""Get entries for name and domain."""
384
args = {'name': name, 'domain': domain}
385
return self.network_rpcapi.get_dns_entries_by_name(context, **args)
388
def create_private_dns_domain(self, context, domain, availability_zone):
389
"""Create a private DNS domain with nova availability zone."""
390
args = {'domain': domain, 'av_zone': availability_zone}
391
return self.network_rpcapi.create_private_dns_domain(context, **args)
394
def create_public_dns_domain(self, context, domain, project=None):
395
"""Create a public DNS domain with optional nova project."""
396
args = {'domain': domain, 'project': project}
397
return self.network_rpcapi.create_public_dns_domain(context, **args)
400
def setup_networks_on_host(self, context, instance, host=None,
402
"""Setup or teardown the network structures on hosts related to
404
host = host or instance['host']
405
# NOTE(tr3buchet): host is passed in cases where we need to setup
406
# or teardown the networks on a host which has been migrated to/from
407
# and instance['host'] is not yet or is no longer equal to
408
args = {'instance_id': instance['id'],
410
'teardown': teardown}
412
self.network_rpcapi.setup_networks_on_host(context, **args)
414
def _is_multi_host(self, context, instance):
416
fixed_ips = self.db.fixed_ip_get_by_instance(context,
418
except exception.FixedIpNotFoundForInstance:
420
network = self.db.network_get(context, fixed_ips[0]['network_id'],
421
project_only='allow_none')
422
return network['multi_host']
424
def _get_floating_ip_addresses(self, context, instance):
425
floating_ips = self.db.instance_floating_address_get_all(context,
427
return [floating_ip['address'] for floating_ip in floating_ips]
430
def migrate_instance_start(self, context, instance, migration):
431
"""Start to migrate the network of an instance."""
433
instance_uuid=instance['uuid'],
434
rxtx_factor=instance['instance_type']['rxtx_factor'],
435
project_id=instance['project_id'],
436
source_compute=migration['source_compute'],
437
dest_compute=migration['dest_compute'],
438
floating_addresses=None,
441
if self._is_multi_host(context, instance):
442
args['floating_addresses'] = \
443
self._get_floating_ip_addresses(context, instance)
444
args['host'] = migration['source_compute']
446
self.network_rpcapi.migrate_instance_start(context, **args)
449
def migrate_instance_finish(self, context, instance, migration):
450
"""Finish migrating the network of an instance."""
452
instance_uuid=instance['uuid'],
453
rxtx_factor=instance['instance_type']['rxtx_factor'],
454
project_id=instance['project_id'],
455
source_compute=migration['source_compute'],
456
dest_compute=migration['dest_compute'],
457
floating_addresses=None,
460
if self._is_multi_host(context, instance):
461
args['floating_addresses'] = \
462
self._get_floating_ip_addresses(context, instance)
463
args['host'] = migration['dest_compute']
465
self.network_rpcapi.migrate_instance_finish(context, **args)