virt: Remove 'get_all_bw_counters' API

This one is a little more involved because there are persistent objects
and versioned notifications to worry about, neither of which we can
remove right now.

Change-Id: Ic7c330ee1cccdc44a2a555c16cb6090eecbf6ce1
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2020-08-31 17:27:18 +01:00
parent 68bc87876f
commit 9d1683f70f
19 changed files with 28 additions and 545 deletions

View File

@ -1,10 +0,0 @@
{
"nova_object.data": {
"network_name": "private",
"out_bytes": 0,
"in_bytes": 0
},
"nova_object.name": "BandwidthPayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
}

View File

@ -2,9 +2,7 @@
"$ref": "InstancePayload.json", "$ref": "InstancePayload.json",
"nova_object.data":{ "nova_object.data":{
"audit_period": {"$ref": "AuditPeriodPayload.json#"}, "audit_period": {"$ref": "AuditPeriodPayload.json#"},
"bandwidth": [ "bandwidth": []
{"$ref": "BandwidthPayload.json#"}
]
}, },
"nova_object.name":"InstanceExistsPayload", "nova_object.name":"InstanceExistsPayload",
"nova_object.namespace":"nova", "nova_object.namespace":"nova",

View File

@ -542,7 +542,6 @@ class ComputeManager(manager.Manager):
self.volume_api = cinder.API() self.volume_api = cinder.API()
self.image_api = glance.API() self.image_api = glance.API()
self._last_bw_usage_poll = 0.0 self._last_bw_usage_poll = 0.0
self._bw_usage_supported = True
self.compute_api = compute.API() self.compute_api = compute.API()
self.compute_rpcapi = compute_rpcapi.ComputeAPI() self.compute_rpcapi = compute_rpcapi.ComputeAPI()
self.compute_task_api = conductor.ComputeTaskAPI() self.compute_task_api = conductor.ComputeTaskAPI()
@ -9398,86 +9397,6 @@ class ComputeManager(manager.Manager):
% (self.host, num_instances, time.time() - start_time)) % (self.host, num_instances, time.time() - start_time))
task_log.end_task() task_log.end_task()
@periodic_task.periodic_task(spacing=CONF.bandwidth_poll_interval)
def _poll_bandwidth_usage(self, context):
if not self._bw_usage_supported:
return
prev_time, start_time = utils.last_completed_audit_period()
curr_time = time.time()
if (curr_time - self._last_bw_usage_poll >
CONF.bandwidth_poll_interval):
self._last_bw_usage_poll = curr_time
LOG.info("Updating bandwidth usage cache")
instances = objects.InstanceList.get_by_host(context,
self.host,
use_slave=True)
try:
bw_counters = self.driver.get_all_bw_counters(instances)
except NotImplementedError:
# NOTE(mdragon): Not all hypervisors have bandwidth polling
# implemented yet. If they don't it doesn't break anything,
# they just don't get the info in the usage events.
# NOTE(PhilDay): Record that its not supported so we can
# skip fast on future calls rather than waste effort getting
# the list of instances.
LOG.info("Bandwidth usage not supported by %(driver)s.",
{'driver': CONF.compute_driver})
self._bw_usage_supported = False
return
refreshed = timeutils.utcnow()
for bw_ctr in bw_counters:
# Allow switching of greenthreads between queries.
greenthread.sleep(0)
bw_in = 0
bw_out = 0
last_ctr_in = None
last_ctr_out = None
usage = objects.BandwidthUsage.get_by_instance_uuid_and_mac(
context, bw_ctr['uuid'], bw_ctr['mac_address'],
start_period=start_time, use_slave=True)
if usage:
bw_in = usage.bw_in
bw_out = usage.bw_out
last_ctr_in = usage.last_ctr_in
last_ctr_out = usage.last_ctr_out
else:
usage = (objects.BandwidthUsage.
get_by_instance_uuid_and_mac(
context, bw_ctr['uuid'], bw_ctr['mac_address'],
start_period=prev_time, use_slave=True))
if usage:
last_ctr_in = usage.last_ctr_in
last_ctr_out = usage.last_ctr_out
if last_ctr_in is not None:
if bw_ctr['bw_in'] < last_ctr_in:
# counter rollover
bw_in += bw_ctr['bw_in']
else:
bw_in += (bw_ctr['bw_in'] - last_ctr_in)
if last_ctr_out is not None:
if bw_ctr['bw_out'] < last_ctr_out:
# counter rollover
bw_out += bw_ctr['bw_out']
else:
bw_out += (bw_ctr['bw_out'] - last_ctr_out)
objects.BandwidthUsage(context=context).create(
bw_ctr['uuid'],
bw_ctr['mac_address'],
bw_in,
bw_out,
bw_ctr['bw_in'],
bw_ctr['bw_out'],
start_period=start_time,
last_refreshed=refreshed)
def _get_host_volume_bdms(self, context, use_slave=False): def _get_host_volume_bdms(self, context, use_slave=False):
"""Return all block device mappings on a compute host.""" """Return all block device mappings on a compute host."""
compute_host_bdms = [] compute_host_bdms = []

View File

@ -356,9 +356,6 @@ def notify_usage_exists(notifier, context, instance_ref, host,
audit_start, audit_end = notifications.audit_period_bounds(current_period) audit_start, audit_end = notifications.audit_period_bounds(current_period)
bw = notifications.bandwidth_usage(context, instance_ref, audit_start,
ignore_missing_network_data)
if system_metadata is None: if system_metadata is None:
system_metadata = utils.instance_sys_meta(instance_ref) system_metadata = utils.instance_sys_meta(instance_ref)
@ -367,7 +364,7 @@ def notify_usage_exists(notifier, context, instance_ref, host,
extra_info = dict(audit_period_beginning=str(audit_start), extra_info = dict(audit_period_beginning=str(audit_start),
audit_period_ending=str(audit_end), audit_period_ending=str(audit_end),
bandwidth=bw, image_meta=image_meta) bandwidth={}, image_meta=image_meta)
if extra_usage_info: if extra_usage_info:
extra_info.update(extra_usage_info) extra_info.update(extra_usage_info)
@ -379,17 +376,11 @@ def notify_usage_exists(notifier, context, instance_ref, host,
audit_period_beginning=audit_start, audit_period_beginning=audit_start,
audit_period_ending=audit_end) audit_period_ending=audit_end)
bandwidth = [instance_notification.BandwidthPayload(
network_name=label,
in_bytes=b['bw_in'],
out_bytes=b['bw_out'])
for label, b in bw.items()]
payload = instance_notification.InstanceExistsPayload( payload = instance_notification.InstanceExistsPayload(
context=context, context=context,
instance=instance_ref, instance=instance_ref,
audit_period=audit_period, audit_period=audit_period,
bandwidth=bandwidth) bandwidth=[])
notification = instance_notification.InstanceExistsNotification( notification = instance_notification.InstanceExistsNotification(
context=context, context=context,

View File

@ -1004,20 +1004,6 @@ Related options:
] ]
interval_opts = [ interval_opts = [
cfg.IntOpt('bandwidth_poll_interval',
default=600,
help="""
Interval to pull network bandwidth usage info.
Not supported on all hypervisors. If a hypervisor doesn't support bandwidth
usage, it will not get the info in the usage events.
Possible values:
* 0: Will run at the default periodic interval.
* Any value < 0: Disables the option.
* Any positive integer in seconds.
"""),
cfg.IntOpt('sync_power_state_interval', cfg.IntOpt('sync_power_state_interval',
default=600, default=600,
help=""" help="""

View File

@ -1229,6 +1229,8 @@ class AgentBuild(BASE, NovaBase, models.SoftDeleteMixin):
md5hash = Column(String(255)) md5hash = Column(String(255))
# TODO(stephenfin): Remove this in the W release or later, once we're sure we
# won't want it back (it's for a XenAPI-only feature)
class BandwidthUsage(BASE, NovaBase, models.SoftDeleteMixin): class BandwidthUsage(BASE, NovaBase, models.SoftDeleteMixin):
"""Cache for instance bandwidth usage data pulled from the hypervisor.""" """Cache for instance bandwidth usage data pulled from the hypervisor."""
__tablename__ = 'bw_usage_cache' __tablename__ = 'bw_usage_cache'

View File

@ -17,8 +17,8 @@
# need to be changed after we moved these function inside the package # need to be changed after we moved these function inside the package
# Todo(gibi): remove these imports after legacy notifications using these are # Todo(gibi): remove these imports after legacy notifications using these are
# transformed to versioned notifications # transformed to versioned notifications
from nova.notifications.base import audit_period_bounds # noqa from nova.notifications.base import audit_period_bounds # noqa
from nova.notifications.base import bandwidth_usage # noqa
from nova.notifications.base import image_meta # noqa from nova.notifications.base import image_meta # noqa
from nova.notifications.base import info_from_instance # noqa from nova.notifications.base import info_from_instance # noqa
from nova.notifications.base import send_update # noqa from nova.notifications.base import send_update # noqa

View File

@ -29,12 +29,8 @@ import nova.conf
import nova.context import nova.context
from nova import exception from nova import exception
from nova.image import glance from nova.image import glance
from nova.network import model as network_model
from nova.network import neutron
from nova.notifications.objects import base as notification_base from nova.notifications.objects import base as notification_base
from nova.notifications.objects import instance as instance_notification from nova.notifications.objects import instance as instance_notification
from nova import objects
from nova.objects import base as obj_base
from nova.objects import fields from nova.objects import fields
from nova import rpc from nova import rpc
from nova import utils from nova import utils
@ -194,8 +190,8 @@ def send_instance_update_notification(context, instance, old_vm_state=None,
payload["audit_period_ending"] = null_safe_isotime(audit_end) payload["audit_period_ending"] = null_safe_isotime(audit_end)
# add bw usage info: # add bw usage info:
bw = bandwidth_usage(context, instance, audit_start) # TODO(stephenfin): Remove this, the feature is dead
payload["bandwidth"] = bw payload["bandwidth"] = {}
# add old display name if it is changed # add old display name if it is changed
if old_display_name: if old_display_name:
@ -226,11 +222,8 @@ def _send_versioned_instance_update(context, instance, payload, host, service):
audit_period_beginning=payload.get('audit_period_beginning'), audit_period_beginning=payload.get('audit_period_beginning'),
audit_period_ending=payload.get('audit_period_ending')) audit_period_ending=payload.get('audit_period_ending'))
bandwidth = [instance_notification.BandwidthPayload( # TODO(stephenfin): Remove this, the feature is dead
network_name=label, bandwidth = []
in_bytes=bw['bw_in'],
out_bytes=bw['bw_out'])
for label, bw in payload['bandwidth'].items()]
versioned_payload = instance_notification.InstanceUpdatePayload( versioned_payload = instance_notification.InstanceUpdatePayload(
context=context, context=context,
@ -271,62 +264,6 @@ def audit_period_bounds(current_period=False):
return (audit_start, audit_end) return (audit_start, audit_end)
def bandwidth_usage(context, instance_ref, audit_start,
ignore_missing_network_data=True):
"""Get bandwidth usage information for the instance for the
specified audit period.
"""
admin_context = context.elevated(read_deleted='yes')
def _get_nwinfo_old_skool():
"""Support for getting network info without objects."""
if (instance_ref.get('info_cache') and
instance_ref['info_cache'].get('network_info') is not None):
cached_info = instance_ref['info_cache']['network_info']
if isinstance(cached_info, network_model.NetworkInfo):
return cached_info
return network_model.NetworkInfo.hydrate(cached_info)
try:
return neutron.API().get_instance_nw_info(admin_context,
instance_ref)
except Exception:
try:
with excutils.save_and_reraise_exception():
LOG.exception('Failed to get nw_info',
instance=instance_ref)
except Exception:
if ignore_missing_network_data:
return
raise
# FIXME(comstud): Temporary as we transition to objects.
if isinstance(instance_ref, obj_base.NovaObject):
nw_info = instance_ref.info_cache.network_info
if nw_info is None:
nw_info = network_model.NetworkInfo()
else:
nw_info = _get_nwinfo_old_skool()
macs = [vif['address'] for vif in nw_info]
uuids = [instance_ref["uuid"]]
bw_usages = objects.BandwidthUsageList.get_by_uuids(admin_context, uuids,
audit_start)
bw = {}
for b in bw_usages:
if b.mac in macs:
label = 'net-name-not-found-%s' % b.mac
for vif in nw_info:
if vif['address'] == b.mac:
label = vif['network']['label']
break
bw[label] = dict(bw_in=b.bw_in, bw_out=b.bw_out)
return bw
def image_meta(system_metadata): def image_meta(system_metadata):
"""Format image metadata for use in notifications from the instance """Format image metadata for use in notifications from the instance
system metadata. system metadata.

View File

@ -300,6 +300,7 @@ class InstanceUpdatePayload(InstancePayload):
fields = { fields = {
'state_update': fields.ObjectField('InstanceStateUpdatePayload'), 'state_update': fields.ObjectField('InstanceStateUpdatePayload'),
'audit_period': fields.ObjectField('AuditPeriodPayload'), 'audit_period': fields.ObjectField('AuditPeriodPayload'),
# TODO(stephenfin): Remove this field in 2.0
'bandwidth': fields.ListOfObjectsField('BandwidthPayload'), 'bandwidth': fields.ListOfObjectsField('BandwidthPayload'),
'old_display_name': fields.StringField(nullable=True), 'old_display_name': fields.StringField(nullable=True),
'tags': fields.ListOfStringsField(), 'tags': fields.ListOfStringsField(),
@ -411,6 +412,7 @@ class IpPayload(base.NotificationPayloadBase):
return ips return ips
# TODO(stephenfin): Drop this object
@nova_base.NovaObjectRegistry.register_notification @nova_base.NovaObjectRegistry.register_notification
class BandwidthPayload(base.NotificationPayloadBase): class BandwidthPayload(base.NotificationPayloadBase):
# Version 1.0: Initial version # Version 1.0: Initial version
@ -722,6 +724,7 @@ class InstanceExistsPayload(InstancePayload):
VERSION = '1.2' VERSION = '1.2'
fields = { fields = {
'audit_period': fields.ObjectField('AuditPeriodPayload'), 'audit_period': fields.ObjectField('AuditPeriodPayload'),
# TODO(stephenfin): Remove this field in version 2.0
'bandwidth': fields.ListOfObjectsField('BandwidthPayload'), 'bandwidth': fields.ListOfObjectsField('BandwidthPayload'),
} }

View File

@ -15,6 +15,8 @@ from nova.objects import base
from nova.objects import fields from nova.objects import fields
# TODO(stephenfin): Remove after W, once we no longer need to worry about the
# versioned notification framework using this
@base.NovaObjectRegistry.register @base.NovaObjectRegistry.register
class BandwidthUsage(base.NovaPersistentObject, base.NovaObject): class BandwidthUsage(base.NovaPersistentObject, base.NovaObject):
# Version 1.0: Initial version # Version 1.0: Initial version
@ -60,7 +62,6 @@ class BandwidthUsage(base.NovaPersistentObject, base.NovaObject):
if db_bw_usage: if db_bw_usage:
return cls._from_db_object(context, cls(), db_bw_usage) return cls._from_db_object(context, cls(), db_bw_usage)
# TODO(stephenfin): Remove 'update_cells' in version 2.0 of the object
@base.serialize_args @base.serialize_args
@base.remotable @base.remotable
def create(self, uuid, mac, bw_in, bw_out, last_ctr_in, def create(self, uuid, mac, bw_in, bw_out, last_ctr_in,
@ -73,6 +74,8 @@ class BandwidthUsage(base.NovaPersistentObject, base.NovaObject):
self._from_db_object(self._context, self, db_bw_usage) self._from_db_object(self._context, self, db_bw_usage)
# TODO(stephenfin): Remove after W, once we no longer need to worry about the
# versioned notification framework using this
@base.NovaObjectRegistry.register @base.NovaObjectRegistry.register
class BandwidthUsageList(base.ObjectListBase, base.NovaObject): class BandwidthUsageList(base.ObjectListBase, base.NovaObject):
# Version 1.0: Initial version # Version 1.0: Initial version

View File

@ -14,7 +14,6 @@ import time
import mock import mock
from nova import context
from nova import exception from nova import exception
from nova.tests import fixtures from nova.tests import fixtures
from nova.tests.functional.api import client from nova.tests.functional.api import client
@ -503,10 +502,6 @@ class TestInstanceNotificationSample(
self._attach_volume_to_server(server, self.cinder.SWAP_OLD_VOL) self._attach_volume_to_server(server, self.cinder.SWAP_OLD_VOL)
# Let's generate some bandwidth usage data.
# Just call the periodic task directly for simplicity
self.compute.manager._poll_bandwidth_usage(context.get_admin_context())
fake_notifier.reset() fake_notifier.reset()
post = { post = {
@ -671,10 +666,6 @@ class TestInstanceNotificationSample(
fake_notifier.reset() fake_notifier.reset()
# Let's generate some bandwidth usage data.
# Just call the periodic task directly for simplicity
self.compute.manager._poll_bandwidth_usage(context.get_admin_context())
self._delete_server(server) self._delete_server(server)
instance_updates = self._get_notifications('instance.update') instance_updates = self._get_notifications('instance.update')
@ -688,14 +679,7 @@ class TestInstanceNotificationSample(
'state_update.old_state': 'active', 'state_update.old_state': 'active',
'state': 'active', 'state': 'active',
'task_state': 'deleting', 'task_state': 'deleting',
'bandwidth': [ 'bandwidth': [],
{'nova_object.namespace': 'nova',
'nova_object.name': 'BandwidthPayload',
'nova_object.data':
{'network_name': 'private',
'out_bytes': 0,
'in_bytes': 0},
'nova_object.version': '1.0'}],
'tags': ["tag1"], 'tags': ["tag1"],
'block_devices': [{ 'block_devices': [{
"nova_object.data": { "nova_object.data": {

View File

@ -22,11 +22,9 @@ import fixtures as std_fixtures
from itertools import chain from itertools import chain
import operator import operator
import sys import sys
import time
import ddt
from castellan import key_manager from castellan import key_manager
import ddt
import mock import mock
from neutronclient.common import exceptions as neutron_exceptions from neutronclient.common import exceptions as neutron_exceptions
from oslo_log import log as logging from oslo_log import log as logging
@ -753,39 +751,6 @@ class ComputeVolumeTestCase(BaseTestCase):
def test_boot_image_no_metadata(self): def test_boot_image_no_metadata(self):
self.test_boot_image_metadata(metadata=False) self.test_boot_image_metadata(metadata=False)
@mock.patch.object(time, 'time')
@mock.patch.object(objects.InstanceList, 'get_by_host')
@mock.patch.object(utils, 'last_completed_audit_period')
@mock.patch.object(fake.FakeDriver, 'get_all_bw_counters')
def test_poll_bandwidth_usage_not_implemented(self, mock_get_counter,
mock_last, mock_get_host, mock_time):
ctxt = context.get_admin_context()
# Following methods will be called
# Note - time called two more times from Log
mock_last.return_value = (0, 0)
mock_time.side_effect = (10, 20, 21)
mock_get_host.return_value = []
mock_get_counter.side_effect = NotImplementedError
self.flags(bandwidth_poll_interval=1)
# The first call will catch a NotImplementedError,
# then LOG.info something below:
self.compute._poll_bandwidth_usage(ctxt)
self.assertIn('Bandwidth usage not supported '
'by %s' % CONF.compute_driver,
self.stdlog.logger.output)
# A second call won't call the stubs again as the bandwidth
# poll is now disabled
self.compute._poll_bandwidth_usage(ctxt)
mock_get_counter.assert_called_once_with([])
mock_last.assert_called_once_with()
mock_get_host.assert_called_once_with(ctxt, 'fake-mini',
use_slave=True)
@mock.patch.object(objects.InstanceList, 'get_by_host') @mock.patch.object(objects.InstanceList, 'get_by_host')
@mock.patch.object(objects.BlockDeviceMappingList, @mock.patch.object(objects.BlockDeviceMappingList,
'get_by_instance_uuid') 'get_by_instance_uuid')

View File

@ -73,7 +73,6 @@ from nova.tests.unit import fake_notifier
from nova.tests.unit.objects import test_instance_fault from nova.tests.unit.objects import test_instance_fault
from nova.tests.unit.objects import test_instance_info_cache from nova.tests.unit.objects import test_instance_info_cache
from nova.tests.unit.objects import test_instance_numa from nova.tests.unit.objects import test_instance_numa
from nova import utils
from nova.virt.block_device import DriverVolumeBlockDevice as driver_bdm_volume from nova.virt.block_device import DriverVolumeBlockDevice as driver_bdm_volume
from nova.virt import driver as virt_driver from nova.virt import driver as virt_driver
from nova.virt import event as virtevent from nova.virt import event as virtevent
@ -5536,41 +5535,6 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
self.assertIn('Trusted image certificates provided on host', self.assertIn('Trusted image certificates provided on host',
six.text_type(ex)) six.text_type(ex))
@mock.patch.object(utils, 'last_completed_audit_period',
return_value=(0, 0))
@mock.patch.object(time, 'time', side_effect=[10, 20, 21])
@mock.patch.object(objects.InstanceList, 'get_by_host', return_value=[])
@mock.patch.object(objects.BandwidthUsage, 'get_by_instance_uuid_and_mac')
@mock.patch.object(db, 'bw_usage_update')
def test_poll_bandwidth_usage(self, bw_usage_update, get_by_uuid_mac,
get_by_host, time, last_completed_audit):
bw_counters = [{'uuid': uuids.instance, 'mac_address': 'fake-mac',
'bw_in': 1, 'bw_out': 2}]
usage = objects.BandwidthUsage()
usage.bw_in = 3
usage.bw_out = 4
usage.last_ctr_in = 0
usage.last_ctr_out = 0
self.flags(bandwidth_poll_interval=1)
get_by_uuid_mac.return_value = usage
_time = timeutils.utcnow()
bw_usage_update.return_value = {'uuid': uuids.instance, 'mac': '',
'start_period': _time, 'last_refreshed': _time, 'bw_in': 0,
'bw_out': 0, 'last_ctr_in': 0, 'last_ctr_out': 0, 'deleted': 0,
'created_at': _time, 'updated_at': _time, 'deleted_at': _time}
with mock.patch.object(self.compute.driver,
'get_all_bw_counters', return_value=bw_counters):
self.compute._poll_bandwidth_usage(self.context)
get_by_uuid_mac.assert_called_once_with(self.context,
uuids.instance, 'fake-mac',
start_period=0, use_slave=True)
# NOTE(sdague): bw_usage_update happens at some time in
# the future, so what last_refreshed is irrelevant.
bw_usage_update.assert_called_once_with(self.context,
uuids.instance,
'fake-mac', 0, 4, 6, 1, 2,
last_refreshed=mock.ANY)
def test_reverts_task_state_instance_not_found(self): def test_reverts_task_state_instance_not_found(self):
# Tests that the reverts_task_state decorator in the compute manager # Tests that the reverts_task_state decorator in the compute manager
# will not trace when an InstanceNotFound is raised. # will not trace when an InstanceNotFound is raised.

View File

@ -5817,200 +5817,6 @@ class CertificateTestCase(test.TestCase, ModelsObjectComparatorMixin):
self._assertEqualObjects(self.created[1], cert[0]) self._assertEqualObjects(self.created[1], cert[0])
class BwUsageTestCase(test.TestCase, ModelsObjectComparatorMixin):
_ignored_keys = ['id', 'deleted', 'deleted_at', 'created_at', 'updated_at']
def setUp(self):
super(BwUsageTestCase, self).setUp()
self.ctxt = context.get_admin_context()
self.useFixture(test.TimeOverride())
def test_bw_usage_get_by_uuids(self):
now = timeutils.utcnow()
start_period = now - datetime.timedelta(seconds=10)
start_period_str = start_period.isoformat()
uuid3_refreshed = now - datetime.timedelta(seconds=5)
uuid3_refreshed_str = uuid3_refreshed.isoformat()
expected_bw_usages = {
'fake_uuid1': {'uuid': 'fake_uuid1',
'mac': 'fake_mac1',
'start_period': start_period,
'bw_in': 100,
'bw_out': 200,
'last_ctr_in': 12345,
'last_ctr_out': 67890,
'last_refreshed': now},
'fake_uuid2': {'uuid': 'fake_uuid2',
'mac': 'fake_mac2',
'start_period': start_period,
'bw_in': 200,
'bw_out': 300,
'last_ctr_in': 22345,
'last_ctr_out': 77890,
'last_refreshed': now},
'fake_uuid3': {'uuid': 'fake_uuid3',
'mac': 'fake_mac3',
'start_period': start_period,
'bw_in': 400,
'bw_out': 500,
'last_ctr_in': 32345,
'last_ctr_out': 87890,
'last_refreshed': uuid3_refreshed}
}
bw_usages = db.bw_usage_get_by_uuids(self.ctxt,
['fake_uuid1', 'fake_uuid2'], start_period_str)
# No matches
self.assertEqual(len(bw_usages), 0)
# Add 3 entries
db.bw_usage_update(self.ctxt, 'fake_uuid1',
'fake_mac1', start_period_str,
100, 200, 12345, 67890)
db.bw_usage_update(self.ctxt, 'fake_uuid2',
'fake_mac2', start_period_str,
100, 200, 42, 42)
# Test explicit refreshed time
db.bw_usage_update(self.ctxt, 'fake_uuid3',
'fake_mac3', start_period_str,
400, 500, 32345, 87890,
last_refreshed=uuid3_refreshed_str)
# Update 2nd entry
db.bw_usage_update(self.ctxt, 'fake_uuid2',
'fake_mac2', start_period_str,
200, 300, 22345, 77890)
bw_usages = db.bw_usage_get_by_uuids(self.ctxt,
['fake_uuid1', 'fake_uuid2', 'fake_uuid3'], start_period_str)
self.assertEqual(len(bw_usages), 3)
for usage in bw_usages:
self._assertEqualObjects(expected_bw_usages[usage['uuid']], usage,
ignored_keys=self._ignored_keys)
def _test_bw_usage_update(self, **expected_bw_usage):
bw_usage = db.bw_usage_update(self.ctxt, **expected_bw_usage)
self._assertEqualObjects(expected_bw_usage, bw_usage,
ignored_keys=self._ignored_keys)
uuid = expected_bw_usage['uuid']
mac = expected_bw_usage['mac']
start_period = expected_bw_usage['start_period']
bw_usage = db.bw_usage_get(self.ctxt, uuid, start_period, mac)
self._assertEqualObjects(expected_bw_usage, bw_usage,
ignored_keys=self._ignored_keys)
def _create_bw_usage(self, context, uuid, mac, start_period, bw_in, bw_out,
last_ctr_in, last_ctr_out, id, last_refreshed=None):
with sqlalchemy_api.get_context_manager(context).writer.using(context):
bwusage = models.BandwidthUsage()
bwusage.start_period = start_period
bwusage.uuid = uuid
bwusage.mac = mac
bwusage.last_refreshed = last_refreshed
bwusage.bw_in = bw_in
bwusage.bw_out = bw_out
bwusage.last_ctr_in = last_ctr_in
bwusage.last_ctr_out = last_ctr_out
bwusage.id = id
bwusage.save(context.session)
def test_bw_usage_update_exactly_one_record(self):
now = timeutils.utcnow()
start_period = now - datetime.timedelta(seconds=10)
uuid = 'fake_uuid'
# create two equal bw_usages with IDs 1 and 2
for id in range(1, 3):
bw_usage = {'uuid': uuid,
'mac': 'fake_mac',
'start_period': start_period,
'bw_in': 100,
'bw_out': 200,
'last_ctr_in': 12345,
'last_ctr_out': 67890,
'last_refreshed': now,
'id': id}
self._create_bw_usage(self.ctxt, **bw_usage)
# check that we have two equal bw_usages
self.assertEqual(
2, len(db.bw_usage_get_by_uuids(self.ctxt, [uuid], start_period)))
# update 'last_ctr_in' field in one bw_usage
updated_bw_usage = {'uuid': uuid,
'mac': 'fake_mac',
'start_period': start_period,
'bw_in': 100,
'bw_out': 200,
'last_ctr_in': 54321,
'last_ctr_out': 67890,
'last_refreshed': now}
result = db.bw_usage_update(self.ctxt, **updated_bw_usage)
# check that only bw_usage with ID 1 was updated
self.assertEqual(1, result['id'])
self._assertEqualObjects(updated_bw_usage, result,
ignored_keys=self._ignored_keys)
def test_bw_usage_get(self):
now = timeutils.utcnow()
start_period = now - datetime.timedelta(seconds=10)
start_period_str = start_period.isoformat()
expected_bw_usage = {'uuid': 'fake_uuid1',
'mac': 'fake_mac1',
'start_period': start_period,
'bw_in': 100,
'bw_out': 200,
'last_ctr_in': 12345,
'last_ctr_out': 67890,
'last_refreshed': now}
bw_usage = db.bw_usage_get(self.ctxt, 'fake_uuid1', start_period_str,
'fake_mac1')
self.assertIsNone(bw_usage)
self._test_bw_usage_update(**expected_bw_usage)
def test_bw_usage_update_new(self):
now = timeutils.utcnow()
start_period = now - datetime.timedelta(seconds=10)
expected_bw_usage = {'uuid': 'fake_uuid1',
'mac': 'fake_mac1',
'start_period': start_period,
'bw_in': 100,
'bw_out': 200,
'last_ctr_in': 12345,
'last_ctr_out': 67890,
'last_refreshed': now}
self._test_bw_usage_update(**expected_bw_usage)
def test_bw_usage_update_existing(self):
now = timeutils.utcnow()
start_period = now - datetime.timedelta(seconds=10)
expected_bw_usage = {'uuid': 'fake_uuid1',
'mac': 'fake_mac1',
'start_period': start_period,
'bw_in': 100,
'bw_out': 200,
'last_ctr_in': 12345,
'last_ctr_out': 67890,
'last_refreshed': now}
self._test_bw_usage_update(**expected_bw_usage)
expected_bw_usage['bw_in'] = 300
expected_bw_usage['bw_out'] = 400
expected_bw_usage['last_ctr_in'] = 23456
expected_bw_usage['last_ctr_out'] = 78901
self._test_bw_usage_update(**expected_bw_usage)
class Ec2TestCase(test.TestCase): class Ec2TestCase(test.TestCase):
def setUp(self): def setUp(self):

View File

@ -63,14 +63,12 @@ class TestSendInstanceUpdateNotification(test.NoDBTestCase):
mock.sentinel.host, mock.sentinel.host,
mock.sentinel.service) mock.sentinel.service)
@mock.patch.object(base, 'bandwidth_usage')
@mock.patch.object(base, '_compute_states_payload') @mock.patch.object(base, '_compute_states_payload')
@mock.patch('nova.rpc.get_notifier') @mock.patch('nova.rpc.get_notifier')
@mock.patch.object(base, 'info_from_instance') @mock.patch.object(base, 'info_from_instance')
def test_send_legacy_instance_update_notification(self, mock_info, def test_send_legacy_instance_update_notification(
mock_get_notifier, self, mock_info, mock_get_notifier, mock_states,
mock_states, ):
mock_bw):
"""Tests the case that versioned notifications are disabled and """Tests the case that versioned notifications are disabled and
assert that this does not prevent sending the unversioned assert that this does not prevent sending the unversioned
instance.update notification. instance.update notification.
@ -132,25 +130,3 @@ class TestSendInstanceUpdateNotification(test.NoDBTestCase):
populate_image_ref_url=False) populate_image_ref_url=False)
mock_gen_image_url.assert_not_called() mock_gen_image_url.assert_not_called()
class TestBandwidthUsage(test.NoDBTestCase):
@mock.patch('nova.context.RequestContext.elevated')
@mock.patch('nova.network.neutron.API')
@mock.patch('nova.objects.BandwidthUsageList.get_by_uuids')
def test_context_elevated(self, mock_get_bw_usage, mock_nw_api,
mock_elevated):
context = nova_context.RequestContext('fake', 'fake')
# We need this to not be a NovaObject so the old school
# get_instance_nw_info will run.
instance = {'uuid': uuids.instance}
audit_start = 'fake'
base.bandwidth_usage(context, instance, audit_start)
network_api = mock_nw_api.return_value
network_api.get_instance_nw_info.assert_called_once_with(
mock_elevated.return_value, instance)
mock_get_bw_usage.assert_called_once_with(
mock_elevated.return_value, [uuids.instance], audit_start)
mock_elevated.assert_called_once_with(read_deleted='yes')

View File

@ -198,21 +198,7 @@ class NotificationsTestCase(test.TestCase):
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS)) self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS)) self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
def get_fake_bandwidth(self): def test_vm_update_with_states(self):
usage = objects.BandwidthUsage(context=self.context)
usage.create(
self.instance.uuid,
mac='DE:AD:BE:EF:00:01',
bw_in=1,
bw_out=2,
last_ctr_in=0,
last_ctr_out=0,
start_period='2012-10-29T13:42:11Z')
return usage
@mock.patch.object(objects.BandwidthUsageList, 'get_by_uuids')
def test_vm_update_with_states(self, mock_bandwidth_list):
mock_bandwidth_list.return_value = [self.get_fake_bandwidth()]
fake_net_info = fake_network.fake_get_instance_nw_info(self) fake_net_info = fake_network.fake_get_instance_nw_info(self)
self.instance.info_cache.network_info = fake_net_info self.instance.info_cache.network_info = fake_net_info
@ -279,17 +265,11 @@ class NotificationsTestCase(test.TestCase):
self.assertEqual(actual_ip['address'], expected_ip['address']) self.assertEqual(actual_ip['address'], expected_ip['address'])
bandwidth = payload['bandwidth'] bandwidth = payload['bandwidth']
self.assertEqual(len(bandwidth), 1) self.assertEqual(0, len(bandwidth))
bandwidth = bandwidth[0]['nova_object.data']
self.assertEqual(bandwidth['in_bytes'], 1)
self.assertEqual(bandwidth['out_bytes'], 2)
self.assertEqual(bandwidth['network_name'], 'test1')
@mock.patch.object(objects.BandwidthUsageList, 'get_by_uuids') def test_task_update_with_states(self):
def test_task_update_with_states(self, mock_bandwidth_list):
self.flags(notify_on_state_change="vm_and_task_state", self.flags(notify_on_state_change="vm_and_task_state",
group='notifications') group='notifications')
mock_bandwidth_list.return_value = [self.get_fake_bandwidth()]
fake_net_info = fake_network.fake_get_instance_nw_info(self) fake_net_info = fake_network.fake_get_instance_nw_info(self)
self.instance.info_cache.network_info = fake_net_info self.instance.info_cache.network_info = fake_net_info

View File

@ -556,16 +556,6 @@ class ComputeDriver(object):
""" """
raise NotImplementedError() raise NotImplementedError()
# TODO(stephenfin): This was only implemented (properly) for XenAPI and
# should be removed.
def get_all_bw_counters(self, instances):
"""Return bandwidth usage counters for each interface on each
running VM.
:param instances: nova.objects.instance.InstanceList
"""
raise NotImplementedError()
def get_all_volume_usage(self, context, compute_host_bdms): def get_all_volume_usage(self, context, compute_host_bdms):
"""Return usage info for volumes attached to vms on """Return usage info for volumes attached to vms on
a given host.- a given host.-

View File

@ -420,18 +420,6 @@ class FakeDriver(driver.ComputeDriver):
maximum=524288, used=0) maximum=524288, used=0)
return diags return diags
def get_all_bw_counters(self, instances):
"""Return bandwidth usage counters for each interface on each
running VM.
"""
bw = []
for instance in instances:
bw.append({'uuid': instance.uuid,
'mac_address': 'fa:16:3e:4c:2c:30',
'bw_in': 0,
'bw_out': 0})
return bw
def get_all_volume_usage(self, context, compute_host_bdms): def get_all_volume_usage(self, context, compute_host_bdms):
"""Return usage info for volumes attached to vms on """Return usage info for volumes attached to vms on
a given host. a given host.

View File

@ -61,3 +61,4 @@ upgrade:
* ``[xenserver] ovs_integration_bridge`` * ``[xenserver] ovs_integration_bridge``
* ``[xenserver] use_join_force`` * ``[xenserver] use_join_force``
* ``[xenserver] console_public_hostname`` * ``[xenserver] console_public_hostname``
* ``[DEFAULT] bandwidth_poll_interval``