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

« back to all changes in this revision

Viewing changes to nova/compute/utils.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-24 13:12:53 UTC
  • mfrom: (1.1.55)
  • Revision ID: package-import@ubuntu.com-20120524131253-ommql08fg1en06ut
Tags: 2012.2~f1-0ubuntu1
* New upstream release.
* Prepare for quantal:
  - Dropped debian/patches/upstream/0006-Use-project_id-in-ec2.cloud._format_image.patch
  - Dropped debian/patches/upstream/0005-Populate-image-properties-with-project_id-again.patch
  - Dropped debian/patches/upstream/0004-Fixed-bug-962840-added-a-test-case.patch
  - Dropped debian/patches/upstream/0003-Allow-unprivileged-RADOS-users-to-access-rbd-volumes.patch
  - Dropped debian/patches/upstream/0002-Stop-libvirt-test-from-deleting-instances-dir.patch
  - Dropped debian/patches/upstream/0001-fix-bug-where-nova-ignores-glance-host-in-imageref.patch 
  - Dropped debian/patches/0001-fix-useexisting-deprecation-warnings.patch
* debian/control: Add python-keystone as a dependency. (LP: #907197)
* debian/patches/kombu_tests_timeout.patch: Refreshed.
* debian/nova.conf, debian/nova-common.postinst: Convert to new ini
  file configuration
* debian/patches/nova-manage_flagfile_location.patch: Refreshed

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
import netaddr
20
20
 
21
 
from nova import context
 
21
import nova.context
22
22
from nova import db
23
23
from nova import exception
24
24
from nova import flags
 
25
from nova import log
25
26
from nova import network
26
27
from nova.network import model as network_model
27
28
from nova.notifier import api as notifier_api
29
30
 
30
31
 
31
32
FLAGS = flags.FLAGS
32
 
 
33
 
 
34
 
def notify_usage_exists(instance_ref, current_period=False):
35
 
    """ Generates 'exists' notification for an instance for usage auditing
36
 
        purposes.
37
 
 
38
 
        Generates usage for last completed period, unless 'current_period'
39
 
        is True."""
40
 
    admin_context = context.get_admin_context(read_deleted='yes')
41
 
    begin, end = utils.current_audit_period()
 
33
LOG = log.getLogger(__name__)
 
34
 
 
35
 
 
36
def notify_usage_exists(context, instance_ref, current_period=False,
 
37
                        ignore_missing_network_data=True,
 
38
                        system_metadata=None, extra_usage_info=None):
 
39
    """Generates 'exists' notification for an instance for usage auditing
 
40
    purposes.
 
41
 
 
42
    :param current_period: if True, this will generate a usage for the
 
43
        current usage period; if False, this will generate a usage for the
 
44
        previous audit period.
 
45
 
 
46
    :param ignore_missing_network_data: if True, log any exceptions generated
 
47
        while getting network info; if False, raise the exception.
 
48
    :param system_metadata: system_metadata DB entries for the instance,
 
49
        if not None.  *NOTE*: Currently unused here in trunk, but needed for
 
50
        potential custom modifications.
 
51
    :param extra_usage_info: Dictionary containing extra values to add or
 
52
        override in the notification if not None.
 
53
    """
 
54
 
 
55
    admin_context = nova.context.get_admin_context(read_deleted='yes')
 
56
    begin, end = utils.last_completed_audit_period()
42
57
    bw = {}
43
58
    if current_period:
44
59
        audit_start = end
53
68
        cached_info = instance_ref['info_cache']['network_info']
54
69
        nw_info = network_model.NetworkInfo.hydrate(cached_info)
55
70
    else:
56
 
        nw_info = network.API().get_instance_nw_info(admin_context,
 
71
        try:
 
72
            nw_info = network.API().get_instance_nw_info(admin_context,
57
73
                                                         instance_ref)
 
74
        except Exception:
 
75
            LOG.exception('Failed to get nw_info', instance=instance_ref)
 
76
            if ignore_missing_network_data:
 
77
                return
 
78
            raise
58
79
 
59
80
    macs = [vif['address'] for vif in nw_info]
60
 
    for b in db.bw_usage_get_by_macs(admin_context,
61
 
                                     macs,
62
 
                                     audit_start):
 
81
    uuids = [instance_ref.uuid]
 
82
 
 
83
    bw_usages = db.bw_usage_get_by_uuids(admin_context, uuids, audit_start)
 
84
    bw_usages = [b for b in bw_usages if b.mac in macs]
 
85
 
 
86
    for b in bw_usages:
63
87
        label = 'net-name-not-found-%s' % b['mac']
64
88
        for vif in nw_info:
65
89
            if vif['address'] == b['mac']:
67
91
                break
68
92
 
69
93
        bw[label] = dict(bw_in=b.bw_in, bw_out=b.bw_out)
70
 
    usage_info = utils.usage_from_instance(instance_ref,
71
 
                          audit_period_beginning=str(audit_start),
72
 
                          audit_period_ending=str(audit_end),
73
 
                          bandwidth=bw)
74
 
    notifier_api.notify('compute.%s' % FLAGS.host,
75
 
                        'compute.instance.exists',
76
 
                        notifier_api.INFO,
77
 
                        usage_info)
 
94
 
 
95
    if system_metadata is None:
 
96
        try:
 
97
            system_metadata = db.instance_system_metadata_get(
 
98
                    context, instance_ref.uuid)
 
99
        except exception.NotFound:
 
100
            system_metadata = {}
 
101
 
 
102
    # add image metadata to the notification:
 
103
    image_meta = {}
 
104
    for md_key, md_value in system_metadata.iteritems():
 
105
        if md_key.startswith('image_'):
 
106
            image_meta[md_key[6:]] = md_value
 
107
 
 
108
    extra_info = dict(audit_period_beginning=str(audit_start),
 
109
                      audit_period_ending=str(audit_end),
 
110
                      bandwidth=bw, image_meta=image_meta)
 
111
 
 
112
    if extra_usage_info:
 
113
        extra_info.update(extra_usage_info)
 
114
 
 
115
    notify_about_instance_usage(context, instance_ref, 'exists',
 
116
            system_metadata=system_metadata, extra_usage_info=extra_info)
78
117
 
79
118
 
80
119
def legacy_network_info(network_model):
147
186
                                        False)
148
187
        should_create_vlan = get_meta(network, 'should_create_vlan', False)
149
188
        gateway = get_ip(subnet_v4['gateway'])
150
 
        dhcp_server = get_meta(subnet_v4, 'dhcp_server', gateway)
 
189
        dhcp_server = get_meta(subnet_v4, 'dhcp_server')
151
190
        network_dict = dict(bridge=network['bridge'],
152
191
                            id=network['id'],
153
192
                            cidr=subnet_v4['cidr'],
190
229
 
191
230
        network_info.append((network_dict, info_dict))
192
231
    return network_info
 
232
 
 
233
 
 
234
def _usage_from_instance(context, instance_ref, network_info,
 
235
        system_metadata, **kw):
 
236
    """
 
237
    Get usage information for an instance which is common to all
 
238
    notifications.
 
239
 
 
240
    :param network_info: network_info provided if not None
 
241
    :param system_metadata: system_metadata DB entries for the instance,
 
242
        if not None.  *NOTE*: Currently unused here in trunk, but needed for
 
243
        potential custom modifications.
 
244
    """
 
245
 
 
246
    def null_safe_str(s):
 
247
        return str(s) if s else ''
 
248
 
 
249
    image_ref_url = utils.generate_image_url(instance_ref['image_ref'])
 
250
 
 
251
    usage_info = dict(
 
252
          tenant_id=instance_ref['project_id'],
 
253
          user_id=instance_ref['user_id'],
 
254
          instance_id=instance_ref['uuid'],
 
255
          instance_type=instance_ref['instance_type']['name'],
 
256
          instance_type_id=instance_ref['instance_type_id'],
 
257
          memory_mb=instance_ref['memory_mb'],
 
258
          disk_gb=instance_ref['root_gb'] + instance_ref['ephemeral_gb'],
 
259
          display_name=instance_ref['display_name'],
 
260
          created_at=str(instance_ref['created_at']),
 
261
          # Nova's deleted vs terminated instance terminology is confusing,
 
262
          # this should be when the instance was deleted (i.e. terminated_at),
 
263
          # not when the db record was deleted. (mdragon)
 
264
          deleted_at=null_safe_str(instance_ref['terminated_at']),
 
265
          launched_at=null_safe_str(instance_ref['launched_at']),
 
266
          image_ref_url=image_ref_url,
 
267
          state=instance_ref['vm_state'],
 
268
          state_description=null_safe_str(instance_ref['task_state']))
 
269
 
 
270
    if network_info is not None:
 
271
        usage_info['fixed_ips'] = network_info.fixed_ips()
 
272
 
 
273
    usage_info.update(kw)
 
274
    return usage_info
 
275
 
 
276
 
 
277
def notify_about_instance_usage(context, instance, event_suffix,
 
278
                                network_info=None, system_metadata=None,
 
279
                                extra_usage_info=None, host=None):
 
280
    """
 
281
    Send a notification about an instance.
 
282
 
 
283
    :param event_suffix: Event type like "delete.start" or "exists"
 
284
    :param network_info: Networking information, if provided.
 
285
    :param system_metadata: system_metadata DB entries for the instance,
 
286
        if provided.
 
287
    :param extra_usage_info: Dictionary containing extra values to add or
 
288
        override in the notification.
 
289
    :param host: Compute host for the instance, if specified.  Default is
 
290
        FLAGS.host
 
291
    """
 
292
 
 
293
    if not host:
 
294
        host = FLAGS.host
 
295
 
 
296
    if not extra_usage_info:
 
297
        extra_usage_info = {}
 
298
 
 
299
    usage_info = _usage_from_instance(context, instance, network_info,
 
300
            system_metadata, **extra_usage_info)
 
301
 
 
302
    notifier_api.notify(context, 'compute.%s' % host,
 
303
                        'compute.instance.%s' % event_suffix,
 
304
                        notifier_api.INFO, usage_info)