~ubuntu-branches/ubuntu/saucy/nova/saucy-proposed

« back to all changes in this revision

Viewing changes to nova/network/api_deprecated.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Chuck Short, Adam Gandelman
  • Date: 2013-02-22 09:27:29 UTC
  • mfrom: (1.1.68)
  • Revision ID: package-import@ubuntu.com-20130222092729-nn3gt8rf97uvts77
Tags: 2013.1.g3-0ubuntu1
[ Chuck Short ]
* New usptream release. 
* debian/patches/debian/patches/fix-ubuntu-tests.patch: Refreshed.
* debian/nova-baremetal.logrotate: Fix logfile path.
* debian/control, debian/nova-spiceproxy.{install, logrotate, upstart}:
  Add spice html5 proxy support.
* debian/nova-novncproxy.upstart: Start on runlevel [2345]
* debian/rules: Call testr directly since run_tests.sh -N gives weird return
  value when tests pass.
* debian/pyddist-overrides: Add websockify.
* debian/nova-common.postinst: Removed config file conversion, since
  the option is no longer available. (LP: #1110567)
* debian/control: Add python-pyasn1 as a dependency.
* debian/control: Add python-oslo-config as a dependency.
* debian/control: Suggest sysfsutils, sg3-utils, multipath-tools for fibre
  channel support.

[ Adam Gandelman ]
* debian/control: Fix typo (websocikfy -> websockify).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
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.
 
6
# All Rights Reserved.
 
7
#
 
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
 
11
#
 
12
#         http://www.apache.org/licenses/LICENSE-2.0
 
13
#
 
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
 
18
#    under the License.
 
19
"""
 
20
This version of the api is deprecated in Grizzly and will be removed.
 
21
 
 
22
It is provided just in case a third party manager is in use.
 
23
"""
 
24
 
 
25
import functools
 
26
import inspect
 
27
 
 
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
 
34
 
 
35
LOG = logging.getLogger(__name__)
 
36
 
 
37
 
 
38
def refresh_cache(f):
 
39
    """
 
40
    Decorator to update the instance_info_cache
 
41
 
 
42
    Requires context and instance as function args
 
43
    """
 
44
    argspec = inspect.getargspec(f)
 
45
 
 
46
    @functools.wraps(f)
 
47
    def wrapper(self, context, *args, **kwargs):
 
48
        res = f(self, context, *args, **kwargs)
 
49
 
 
50
        try:
 
51
            # get the instance from arguments (or raise ValueError)
 
52
            instance = kwargs.get('instance')
 
53
            if not instance:
 
54
                instance = args[argspec.args.index('instance') - 2]
 
55
        except ValueError:
 
56
            msg = _('instance is a required argument to use @refresh_cache')
 
57
            raise Exception(msg)
 
58
 
 
59
        update_instance_cache_with_nw_info(self, context, instance,
 
60
                                           nw_info=res)
 
61
 
 
62
        # return the original function's return value
 
63
        return res
 
64
    return wrapper
 
65
 
 
66
 
 
67
def update_instance_cache_with_nw_info(api, context, instance,
 
68
                                        nw_info=None):
 
69
 
 
70
    try:
 
71
        if not isinstance(nw_info, network_model.NetworkInfo):
 
72
            nw_info = None
 
73
        if not nw_info:
 
74
            nw_info = api._get_instance_nw_info(context, instance)
 
75
        # update cache
 
76
        cache = {'network_info': nw_info.json()}
 
77
        api.db.instance_info_cache_update(context, instance['uuid'], cache)
 
78
    except Exception:
 
79
        LOG.exception(_('Failed storing info cache'), instance=instance)
 
80
 
 
81
 
 
82
def wrap_check_policy(func):
 
83
    """Check policy corresponding to the wrapped methods prior to execution."""
 
84
 
 
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)
 
90
 
 
91
    return wrapped
 
92
 
 
93
 
 
94
def check_policy(context, action):
 
95
    target = {
 
96
        'project_id': context.project_id,
 
97
        'user_id': context.user_id,
 
98
    }
 
99
    _action = 'network:%s' % action
 
100
    policy.enforce(context, _action, target)
 
101
 
 
102
 
 
103
class API(base.Base):
 
104
    """API for doing networking via the nova-network network manager.
 
105
 
 
106
    This is a pluggable module - other implementations do networking via
 
107
    other services (such as Quantum).
 
108
    """
 
109
 
 
110
    _sentinel = object()
 
111
 
 
112
    def __init__(self, **kwargs):
 
113
        self.network_rpcapi = network_rpcapi.NetworkAPI()
 
114
        super(API, self).__init__(**kwargs)
 
115
 
 
116
    @wrap_check_policy
 
117
    def get_all(self, context):
 
118
        return self.network_rpcapi.get_all_networks(context)
 
119
 
 
120
    @wrap_check_policy
 
121
    def get(self, context, network_uuid):
 
122
        return self.network_rpcapi.get_network(context, network_uuid)
 
123
 
 
124
    @wrap_check_policy
 
125
    def create(self, context, **kwargs):
 
126
        return self.network_rpcapi.create_networks(context, **kwargs)
 
127
 
 
128
    @wrap_check_policy
 
129
    def delete(self, context, network_uuid):
 
130
        return self.network_rpcapi.delete_network(context, network_uuid, None)
 
131
 
 
132
    @wrap_check_policy
 
133
    def disassociate(self, context, network_uuid):
 
134
        return self.network_rpcapi.disassociate_network(context, network_uuid)
 
135
 
 
136
    @wrap_check_policy
 
137
    def get_fixed_ip(self, context, id):
 
138
        return self.network_rpcapi.get_fixed_ip(context, id)
 
139
 
 
140
    @wrap_check_policy
 
141
    def get_fixed_ip_by_address(self, context, address):
 
142
        return self.network_rpcapi.get_fixed_ip_by_address(context, address)
 
143
 
 
144
    @wrap_check_policy
 
145
    def get_floating_ip(self, context, id):
 
146
        return self.network_rpcapi.get_floating_ip(context, id)
 
147
 
 
148
    @wrap_check_policy
 
149
    def get_floating_ip_pools(self, context):
 
150
        return self.network_rpcapi.get_floating_ip_pools(context)
 
151
 
 
152
    @wrap_check_policy
 
153
    def get_floating_ip_by_address(self, context, address):
 
154
        return self.network_rpcapi.get_floating_ip_by_address(context, address)
 
155
 
 
156
    @wrap_check_policy
 
157
    def get_floating_ips_by_project(self, context):
 
158
        return self.network_rpcapi.get_floating_ips_by_project(context)
 
159
 
 
160
    @wrap_check_policy
 
161
    def get_floating_ips_by_fixed_address(self, context, fixed_address):
 
162
        return self.network_rpcapi.get_floating_ips_by_fixed_address(context,
 
163
                fixed_address)
 
164
 
 
165
    @wrap_check_policy
 
166
    def get_backdoor_port(self, context, host):
 
167
        return self.network_rpcapi.get_backdoor_port(context, host)
 
168
 
 
169
    @wrap_check_policy
 
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,
 
173
                address)
 
174
 
 
175
    @wrap_check_policy
 
176
    def get_vifs_by_instance(self, context, instance):
 
177
        return self.network_rpcapi.get_vifs_by_instance(context,
 
178
                instance['id'])
 
179
 
 
180
    @wrap_check_policy
 
181
    def get_vif_by_mac_address(self, context, mac_address):
 
182
        return self.network_rpcapi.get_vif_by_mac_address(context, mac_address)
 
183
 
 
184
    @wrap_check_policy
 
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
 
190
        #             at some point.
 
191
        return self.network_rpcapi.allocate_floating_ip(context,
 
192
                context.project_id, pool, False)
 
193
 
 
194
    @wrap_check_policy
 
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)
 
200
 
 
201
    @wrap_check_policy
 
202
    @refresh_cache
 
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.
 
207
 
 
208
        ensures floating ip is allocated to the project in context
 
209
        """
 
210
        orig_instance_uuid = self.network_rpcapi.associate_floating_ip(context,
 
211
                floating_address, fixed_address, affect_auto_assigned)
 
212
 
 
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,
 
219
                                                         orig_instance_uuid)
 
220
 
 
221
            # purge cached nw info for the original instance
 
222
            update_instance_cache_with_nw_info(self, context, orig_instance)
 
223
 
 
224
    @wrap_check_policy
 
225
    @refresh_cache
 
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)
 
231
 
 
232
    @wrap_check_policy
 
233
    @refresh_cache
 
234
    def allocate_for_instance(self, context, instance, vpn,
 
235
                              requested_networks, macs=None):
 
236
        """Allocates all network structures for an instance.
 
237
 
 
238
        TODO(someone): document the rest of these parameters.
 
239
 
 
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
 
245
        """
 
246
        args = {}
 
247
        args['vpn'] = vpn
 
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)
 
255
 
 
256
        return network_model.NetworkInfo.hydrate(nw_info)
 
257
 
 
258
    @wrap_check_policy
 
259
    def deallocate_for_instance(self, context, instance):
 
260
        """Deallocates all network structures related to instance."""
 
261
 
 
262
        args = {}
 
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)
 
267
 
 
268
    @wrap_check_policy
 
269
    @refresh_cache
 
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)
 
276
 
 
277
    @wrap_check_policy
 
278
    @refresh_cache
 
279
    def remove_fixed_ip_from_instance(self, context, instance, address):
 
280
        """Removes a fixed ip from instance from specified network."""
 
281
 
 
282
        args = {'instance_id': instance['uuid'],
 
283
                'host': instance['host'],
 
284
                'address': address}
 
285
        self.network_rpcapi.remove_fixed_ip_from_instance(context, **args)
 
286
 
 
287
    @wrap_check_policy
 
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,
 
291
                network_uuid)
 
292
 
 
293
    @wrap_check_policy
 
294
    def associate(self, context, network_uuid, host=_sentinel,
 
295
                  project=_sentinel):
 
296
        """Associate or disassociate host or project to network."""
 
297
        associations = {}
 
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)
 
303
 
 
304
    @wrap_check_policy
 
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)
 
308
        if update_cache:
 
309
            update_instance_cache_with_nw_info(self, context, instance,
 
310
                                                result)
 
311
        return result
 
312
 
 
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)
 
321
 
 
322
        return network_model.NetworkInfo.hydrate(nw_info)
 
323
 
 
324
    @wrap_check_policy
 
325
    def validate_networks(self, context, requested_networks):
 
326
        """validate the networks passed at the time of creating
 
327
        the server
 
328
        """
 
329
        return self.network_rpcapi.validate_networks(context,
 
330
                                                     requested_networks)
 
331
 
 
332
    @wrap_check_policy
 
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
 
336
        """
 
337
        return self.network_rpcapi.get_instance_uuids_by_ip_filter(context,
 
338
                                                                   filters)
 
339
 
 
340
    @wrap_check_policy
 
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.
 
344
        """
 
345
        return self.network_rpcapi.get_dns_domains(context)
 
346
 
 
347
    @wrap_check_policy
 
348
    def add_dns_entry(self, context, address, name, dns_type, domain):
 
349
        """Create specified DNS entry for address."""
 
350
        args = {'address': address,
 
351
                'name': name,
 
352
                'dns_type': dns_type,
 
353
                'domain': domain}
 
354
        return self.network_rpcapi.add_dns_entry(context, **args)
 
355
 
 
356
    @wrap_check_policy
 
357
    def modify_dns_entry(self, context, name, address, domain):
 
358
        """Create specified DNS entry for address."""
 
359
        args = {'address': address,
 
360
                'name': name,
 
361
                'domain': domain}
 
362
        return self.network_rpcapi.modify_dns_entry(context, **args)
 
363
 
 
364
    @wrap_check_policy
 
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)
 
369
 
 
370
    @wrap_check_policy
 
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)
 
374
 
 
375
    @wrap_check_policy
 
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)
 
380
 
 
381
    @wrap_check_policy
 
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)
 
386
 
 
387
    @wrap_check_policy
 
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)
 
392
 
 
393
    @wrap_check_policy
 
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)
 
398
 
 
399
    @wrap_check_policy
 
400
    def setup_networks_on_host(self, context, instance, host=None,
 
401
                                                        teardown=False):
 
402
        """Setup or teardown the network structures on hosts related to
 
403
           instance"""
 
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'],
 
409
                'host': host,
 
410
                'teardown': teardown}
 
411
 
 
412
        self.network_rpcapi.setup_networks_on_host(context, **args)
 
413
 
 
414
    def _is_multi_host(self, context, instance):
 
415
        try:
 
416
            fixed_ips = self.db.fixed_ip_get_by_instance(context,
 
417
                                                         instance['uuid'])
 
418
        except exception.FixedIpNotFoundForInstance:
 
419
            return False
 
420
        network = self.db.network_get(context, fixed_ips[0]['network_id'],
 
421
                                      project_only='allow_none')
 
422
        return network['multi_host']
 
423
 
 
424
    def _get_floating_ip_addresses(self, context, instance):
 
425
        floating_ips = self.db.instance_floating_address_get_all(context,
 
426
                                                            instance['uuid'])
 
427
        return [floating_ip['address'] for floating_ip in floating_ips]
 
428
 
 
429
    @wrap_check_policy
 
430
    def migrate_instance_start(self, context, instance, migration):
 
431
        """Start to migrate the network of an instance."""
 
432
        args = dict(
 
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,
 
439
        )
 
440
 
 
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']
 
445
 
 
446
        self.network_rpcapi.migrate_instance_start(context, **args)
 
447
 
 
448
    @wrap_check_policy
 
449
    def migrate_instance_finish(self, context, instance, migration):
 
450
        """Finish migrating the network of an instance."""
 
451
        args = dict(
 
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,
 
458
        )
 
459
 
 
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']
 
464
 
 
465
        self.network_rpcapi.migrate_instance_finish(context, **args)