Merge "objects: Remove 'bandwidth' fields from notifications"

This commit is contained in:
Zuul
2021-11-10 18:02:50 +00:00
committed by Gerrit Code Review
15 changed files with 41 additions and 406 deletions
@@ -1,10 +1,9 @@
{
"$ref": "InstancePayload.json",
"nova_object.data":{
"audit_period": {"$ref": "AuditPeriodPayload.json#"},
"bandwidth": []
"audit_period": {"$ref": "AuditPeriodPayload.json#"}
},
"nova_object.name":"InstanceExistsPayload",
"nova_object.namespace":"nova",
"nova_object.version":"1.2"
"nova_object.version":"2.0"
}
@@ -10,7 +10,6 @@
"nova_object.namespace": "nova",
"nova_object.version": "1.0"
},
"bandwidth": [],
"block_devices": [],
"old_display_name": null,
"state_update": {
@@ -29,5 +28,5 @@
},
"nova_object.name": "InstanceUpdatePayload",
"nova_object.namespace": "nova",
"nova_object.version": "1.9"
}
"nova_object.version": "2.0"
}
+11 -7
View File
@@ -370,7 +370,7 @@ def notify_usage_exists(notifier, context, instance_ref, host,
extra_info = dict(audit_period_beginning=str(audit_start),
audit_period_ending=str(audit_end),
bandwidth={}, image_meta=image_meta)
image_meta=image_meta)
if extra_usage_info:
extra_info.update(extra_usage_info)
@@ -379,24 +379,28 @@ def notify_usage_exists(notifier, context, instance_ref, host,
extra_usage_info=extra_info)
audit_period = instance_notification.AuditPeriodPayload(
audit_period_beginning=audit_start,
audit_period_ending=audit_end)
audit_period_beginning=audit_start,
audit_period_ending=audit_end,
)
payload = instance_notification.InstanceExistsPayload(
context=context,
instance=instance_ref,
audit_period=audit_period,
bandwidth=[])
)
notification = instance_notification.InstanceExistsNotification(
context=context,
priority=fields.NotificationPriority.INFO,
publisher=notification_base.NotificationPublisher(
host=host, source=fields.NotificationSource.COMPUTE),
host=host, source=fields.NotificationSource.COMPUTE,
),
event_type=notification_base.EventType(
object='instance',
action=fields.NotificationAction.EXISTS),
payload=payload)
action=fields.NotificationAction.EXISTS,
),
payload=payload,
)
notification.emit(context)
-83
View File
@@ -3545,89 +3545,6 @@ def instance_system_metadata_update(context, instance_uuid, metadata, delete):
return metadata
####################
@require_context
@pick_context_manager_reader_allow_async
def bw_usage_get(context, uuid, start_period, mac):
"""Return bw usage for instance and mac in a given audit period."""
values = {'start_period': start_period}
values = convert_objects_related_datetimes(values, 'start_period')
return model_query(context, models.BandwidthUsage, read_deleted="yes").\
filter_by(start_period=values['start_period']).\
filter_by(uuid=uuid).\
filter_by(mac=mac).\
first()
@require_context
@pick_context_manager_reader_allow_async
def bw_usage_get_by_uuids(context, uuids, start_period):
"""Return bw usages for instance(s) in a given audit period."""
values = {'start_period': start_period}
values = convert_objects_related_datetimes(values, 'start_period')
return (
model_query(context, models.BandwidthUsage, read_deleted="yes").
filter(models.BandwidthUsage.uuid.in_(uuids)).
filter_by(start_period=values['start_period']).
all()
)
@require_context
@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
@pick_context_manager_writer
def bw_usage_update(
context, uuid, mac, start_period, bw_in, bw_out, last_ctr_in, last_ctr_out,
last_refreshed=None,
):
"""Update cached bandwidth usage for an instance's network based on mac
address. Creates new record if needed.
"""
if last_refreshed is None:
last_refreshed = timeutils.utcnow()
# NOTE(comstud): More often than not, we'll be updating records vs
# creating records. Optimize accordingly, trying to update existing
# records. Fall back to creation when no rows are updated.
ts_values = {'last_refreshed': last_refreshed,
'start_period': start_period}
ts_keys = ('start_period', 'last_refreshed')
ts_values = convert_objects_related_datetimes(ts_values, *ts_keys)
values = {'last_refreshed': ts_values['last_refreshed'],
'last_ctr_in': last_ctr_in,
'last_ctr_out': last_ctr_out,
'bw_in': bw_in,
'bw_out': bw_out}
# NOTE(pkholkin): order_by() is needed here to ensure that the
# same record is updated every time. It can be removed after adding
# unique constraint to this model.
bw_usage = model_query(context, models.BandwidthUsage,
read_deleted='yes').\
filter_by(start_period=ts_values['start_period']).\
filter_by(uuid=uuid).\
filter_by(mac=mac).\
order_by(expression.asc(models.BandwidthUsage.id)).first()
if bw_usage:
bw_usage.update(values)
return bw_usage
bwusage = models.BandwidthUsage()
bwusage.start_period = ts_values['start_period']
bwusage.uuid = uuid
bwusage.mac = mac
bwusage.last_refreshed = ts_values['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.save(context.session)
return bwusage
####################
-8
View File
@@ -189,10 +189,6 @@ def send_instance_update_notification(context, instance, old_vm_state=None,
payload["audit_period_beginning"] = null_safe_isotime(audit_start)
payload["audit_period_ending"] = null_safe_isotime(audit_end)
# add bw usage info:
# TODO(stephenfin): Remove this, the feature is dead
payload["bandwidth"] = {}
# add old display name if it is changed
if old_display_name:
payload["old_display_name"] = old_display_name
@@ -222,15 +218,11 @@ def _send_versioned_instance_update(context, instance, payload, host, service):
audit_period_beginning=payload.get('audit_period_beginning'),
audit_period_ending=payload.get('audit_period_ending'))
# TODO(stephenfin): Remove this, the feature is dead
bandwidth = []
versioned_payload = instance_notification.InstanceUpdatePayload(
context=context,
instance=instance,
state_update=state_update,
audit_period=audit_period,
bandwidth=bandwidth,
old_display_name=payload.get('old_display_name'))
notification = instance_notification.InstanceUpdateNotification(
+10 -33
View File
@@ -296,23 +296,21 @@ class InstanceUpdatePayload(InstancePayload):
# Version 1.8: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.9: Added locked_reason field to InstancePayload
VERSION = '1.9'
# Version 2.0: Remove bandwidth field
VERSION = '2.0'
fields = {
'state_update': fields.ObjectField('InstanceStateUpdatePayload'),
'audit_period': fields.ObjectField('AuditPeriodPayload'),
# TODO(stephenfin): Remove this field in 2.0
'bandwidth': fields.ListOfObjectsField('BandwidthPayload'),
'old_display_name': fields.StringField(nullable=True),
'tags': fields.ListOfStringsField(),
}
def __init__(self, context, instance, state_update, audit_period,
bandwidth, old_display_name):
super(InstanceUpdatePayload, self).__init__(
context=context, instance=instance)
def __init__(
self, context, instance, state_update, audit_period, old_display_name,
):
super().__init__(context=context, instance=instance)
self.state_update = state_update
self.audit_period = audit_period
self.bandwidth = bandwidth
self.old_display_name = old_display_name
self.tags = [instance_tag.tag
for instance_tag in instance.tags.objects]
@@ -412,24 +410,6 @@ class IpPayload(base.NotificationPayloadBase):
return ips
# TODO(stephenfin): Drop this object
@nova_base.NovaObjectRegistry.register_notification
class BandwidthPayload(base.NotificationPayloadBase):
# Version 1.0: Initial version
VERSION = '1.0'
fields = {
'network_name': fields.StringField(),
'in_bytes': fields.IntegerField(),
'out_bytes': fields.IntegerField(),
}
def __init__(self, network_name, in_bytes, out_bytes):
super(BandwidthPayload, self).__init__()
self.network_name = network_name
self.in_bytes = in_bytes
self.out_bytes = out_bytes
@nova_base.NovaObjectRegistry.register_notification
class AuditPeriodPayload(base.NotificationPayloadBase):
# Version 1.0: Initial version
@@ -721,18 +701,15 @@ class InstanceExistsPayload(InstancePayload):
# Version 1.1: Added action_initiator_user and action_initiator_project to
# InstancePayload
# Version 1.2: Added locked_reason field to InstancePayload
VERSION = '1.2'
# Version 2.0: Remove bandwidth field
VERSION = '2.0'
fields = {
'audit_period': fields.ObjectField('AuditPeriodPayload'),
# TODO(stephenfin): Remove this field in version 2.0
'bandwidth': fields.ListOfObjectsField('BandwidthPayload'),
}
def __init__(self, context, instance, audit_period, bandwidth):
super(InstanceExistsPayload, self).__init__(context=context,
instance=instance)
def __init__(self, context, instance, audit_period):
super().__init__(context=context, instance=instance)
self.audit_period = audit_period
self.bandwidth = bandwidth
@base.notification_sample('instance-exists.json')
-1
View File
@@ -25,7 +25,6 @@ def register_all():
# function in order for it to be registered by services that may
# need to receive it via RPC.
__import__('nova.objects.aggregate')
__import__('nova.objects.bandwidth_usage')
__import__('nova.objects.block_device')
__import__('nova.objects.build_request')
__import__('nova.objects.cell_mapping')
-102
View File
@@ -1,102 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from nova.db.main import api as db
from nova.objects import base
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
class BandwidthUsage(base.NovaPersistentObject, base.NovaObject):
# Version 1.0: Initial version
# Version 1.1: Add use_slave to get_by_instance_uuid_and_mac
# Version 1.2: Add update_cells to create
VERSION = '1.2'
fields = {
'instance_uuid': fields.UUIDField(),
'mac': fields.StringField(),
'start_period': fields.DateTimeField(),
'last_refreshed': fields.DateTimeField(),
'bw_in': fields.IntegerField(),
'bw_out': fields.IntegerField(),
'last_ctr_in': fields.IntegerField(),
'last_ctr_out': fields.IntegerField()
}
@staticmethod
def _from_db_object(context, bw_usage, db_bw_usage):
for field in bw_usage.fields:
if field == 'instance_uuid':
setattr(bw_usage, field, db_bw_usage['uuid'])
else:
setattr(bw_usage, field, db_bw_usage[field])
bw_usage._context = context
bw_usage.obj_reset_changes()
return bw_usage
@staticmethod
@db.select_db_reader_mode
def _db_bw_usage_get(context, uuid, start_period, mac, use_slave=False):
return db.bw_usage_get(context, uuid=uuid, start_period=start_period,
mac=mac)
@base.serialize_args
@base.remotable_classmethod
def get_by_instance_uuid_and_mac(cls, context, instance_uuid, mac,
start_period=None, use_slave=False):
db_bw_usage = cls._db_bw_usage_get(context, uuid=instance_uuid,
start_period=start_period, mac=mac,
use_slave=use_slave)
if db_bw_usage:
return cls._from_db_object(context, cls(), db_bw_usage)
@base.serialize_args
@base.remotable
def create(self, uuid, mac, bw_in, bw_out, last_ctr_in,
last_ctr_out, start_period=None, last_refreshed=None,
update_cells=True):
db_bw_usage = db.bw_usage_update(
self._context, uuid, mac, start_period, bw_in, bw_out,
last_ctr_in, last_ctr_out, last_refreshed=last_refreshed)
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
class BandwidthUsageList(base.ObjectListBase, base.NovaObject):
# Version 1.0: Initial version
# Version 1.1: Add use_slave to get_by_uuids
# Version 1.2: BandwidthUsage <= version 1.2
VERSION = '1.2'
fields = {
'objects': fields.ListOfObjectsField('BandwidthUsage'),
}
@staticmethod
@db.select_db_reader_mode
def _db_bw_usage_get_by_uuids(context, uuids, start_period,
use_slave=False):
return db.bw_usage_get_by_uuids(context, uuids=uuids,
start_period=start_period)
@base.serialize_args
@base.remotable_classmethod
def get_by_uuids(cls, context, uuids, start_period=None, use_slave=False):
db_bw_usages = cls._db_bw_usage_get_by_uuids(context, uuids=uuids,
start_period=start_period,
use_slave=use_slave)
return base.obj_make_list(context, cls(), BandwidthUsage, db_bw_usages)
@@ -679,7 +679,6 @@ class TestInstanceNotificationSample(
'state_update.old_state': 'active',
'state': 'active',
'task_state': 'deleting',
'bandwidth': [],
'tags': ["tag1"],
'block_devices': [{
"nova_object.data": {
@@ -705,7 +704,6 @@ class TestInstanceNotificationSample(
'terminated_at': '2012-10-29T13:42:11Z',
'ip_addresses': [],
'power_state': 'pending',
'bandwidth': [],
'tags': ["tag1"],
'block_devices': [{
"nova_object.data": {
@@ -399,7 +399,7 @@ class UsageInfoTestCase(test.TestCase):
self.assertEqual(str(payload['instance_flavor_id']), str(flavor_id))
for attr in ('display_name', 'created_at', 'launched_at',
'state', 'state_description',
'bandwidth', 'audit_period_beginning',
'audit_period_beginning',
'audit_period_ending', 'image_meta'):
self.assertIn(attr, payload,
"Key %s not in payload" % attr)
@@ -430,7 +430,7 @@ class UsageInfoTestCase(test.TestCase):
self.assertEqual(str(flavor['flavorid']), str(flavorid))
for attr in ('display_name', 'created_at', 'launched_at',
'state', 'bandwidth', 'audit_period'):
'state', 'audit_period'):
self.assertIn(attr, payload,
"Key %s not in payload" % attr)
@@ -463,7 +463,7 @@ class UsageInfoTestCase(test.TestCase):
self.assertEqual(str(payload['instance_flavor_id']), str(flavor_id))
for attr in ('display_name', 'created_at', 'launched_at',
'state', 'state_description',
'bandwidth', 'audit_period_beginning',
'audit_period_beginning',
'audit_period_ending', 'image_meta'):
self.assertIn(attr, payload, "Key %s not in payload" % attr)
self.assertEqual(payload['image_meta'],
@@ -732,7 +732,7 @@ class UsageInfoTestCase(test.TestCase):
exception_payload['exception_message'])
self.assertEqual('test_notify_about_volume_swap_with_error',
exception_payload['function_name'])
self.assertEqual('nova.tests.unit.compute.test_compute_utils',
self.assertEqual('nova.tests.unit.compute.test_utils',
exception_payload['module_name'])
self.assertIn('test_notify_about_volume_swap_with_error',
exception_payload['traceback'])
@@ -827,7 +827,7 @@ class UsageInfoTestCase(test.TestCase):
str(payload['instance_flavor_id']))
for attr in ('display_name', 'created_at', 'launched_at',
'state', 'state_description',
'bandwidth', 'audit_period_beginning',
'audit_period_beginning',
'audit_period_ending', 'image_meta'):
self.assertIn(attr, payload, "Key %s not in payload" % attr)
self.assertEqual(payload['image_meta'], {})
@@ -371,7 +371,6 @@ notification_object_data = {
'AggregateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'AggregatePayload': '1.1-1eb9adcc4440d8627de6ec37c6398746',
'AuditPeriodPayload': '1.0-2b429dd307b8374636703b843fa3f9cb',
'BandwidthPayload': '1.0-ee2616a7690ab78406842a2b68e34130',
'BlockDevicePayload': '1.0-29751e1b6d41b1454e36768a1e764df8',
'CellMappingPayload': '2.0-8acd412eb4edff1cd2ecb9867feeb243',
'ComputeTaskNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
@@ -410,14 +409,14 @@ notification_object_data = {
'1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceActionSnapshotPayload': '1.9-c3e0bbaaefafdfa2f8e6e504c2c9b12c',
'InstanceExistsNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceExistsPayload': '1.2-e082c02438ee57164829afaeee3bf7f8',
'InstanceExistsPayload': '2.0-802d380c61cba2edb905c45052c612b0',
'InstanceNUMACellPayload': '1.2-a367add3378c71c21c817ab2b23db3bf',
'InstanceNUMATopologyPayload': '1.0-247361b152047c18ae9ad1da2544a3c9',
'InstancePCIRequestPayload': '1.1-bda86a95ef04bdc27789342466b81bb5',
'InstancePCIRequestsPayload': '1.0-6751cffe0c0fabd212aad624f672429a',
'InstanceStateUpdatePayload': '1.0-07e111c0fa0f6db0f79b0726d593e3da',
'InstanceUpdateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'InstanceUpdatePayload': '1.9-0295e45efc2c6ba98fbca77bbddf882d',
'InstanceUpdatePayload': '2.0-6ad65963b4ef57210544651e1077ac97',
'IpPayload': '1.0-8ecf567a99e516d4af094439a7632d34',
'KeypairNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
'KeypairPayload': '1.0-6daebbbde0e1bf35c1556b1ecd9385c1',
@@ -1,151 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import iso8601
import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import timeutils
from nova import context
from nova.db.main import api as db
from nova.objects import bandwidth_usage
from nova import test
from nova.tests.unit.objects import test_objects
class _TestBandwidthUsage(test.TestCase):
def setUp(self):
super(_TestBandwidthUsage, self).setUp()
self.user_id = 'fake_user'
self.project_id = 'fake_project'
self.context = context.RequestContext(self.user_id, self.project_id)
now, start_period = self._time_now_and_start_period()
self.expected_bw_usage = self._fake_bw_usage(
time=now, start_period=start_period)
@staticmethod
def _compare(test, db, obj, ignored_fields=None):
if ignored_fields is None:
ignored_fields = []
for field, value in db.items():
if field in ignored_fields:
continue
obj_field = field
if obj_field == 'uuid':
obj_field = 'instance_uuid'
test.assertEqual(db[field], getattr(obj, obj_field),
'Field %s is not equal' % field)
@staticmethod
def _fake_bw_usage(time=None, start_period=None, bw_in=100,
bw_out=200, last_ctr_in=12345, last_ctr_out=67890):
fake_bw_usage = {
'created_at': None,
'updated_at': None,
'deleted_at': None,
'deleted': 0,
'uuid': uuids.instance,
'mac': 'fake_mac1',
'start_period': start_period,
'bw_in': bw_in,
'bw_out': bw_out,
'last_ctr_in': last_ctr_in,
'last_ctr_out': last_ctr_out,
'last_refreshed': time
}
return fake_bw_usage
@staticmethod
def _time_now_and_start_period():
now = timeutils.utcnow().replace(tzinfo=iso8601.UTC,
microsecond=0)
start_period = now - datetime.timedelta(seconds=10)
return now, start_period
@mock.patch.object(db, 'bw_usage_get')
def test_get_by_instance_uuid_and_mac(self, mock_get):
mock_get.return_value = self.expected_bw_usage
bw_usage = bandwidth_usage.BandwidthUsage.get_by_instance_uuid_and_mac(
self.context, uuids.instance, 'fake_mac',
start_period=self.expected_bw_usage['start_period'])
self._compare(self, self.expected_bw_usage, bw_usage)
@mock.patch.object(db, 'bw_usage_get_by_uuids')
def test_get_by_uuids(self, mock_get_by_uuids):
mock_get_by_uuids.return_value = [self.expected_bw_usage]
bw_usages = bandwidth_usage.BandwidthUsageList.get_by_uuids(
self.context, [uuids.instance],
start_period=self.expected_bw_usage['start_period'])
self.assertEqual(1, len(bw_usages))
self._compare(self, self.expected_bw_usage, bw_usages[0])
@mock.patch.object(db, 'bw_usage_update')
def test_create(self, mock_create):
mock_create.return_value = self.expected_bw_usage
bw_usage = bandwidth_usage.BandwidthUsage(context=self.context)
bw_usage.create(uuids.instance, 'fake_mac',
100, 200, 12345, 67890,
start_period=self.expected_bw_usage['start_period'])
self._compare(self, self.expected_bw_usage, bw_usage)
def test_update_with_db(self):
expected_bw_usage1 = self._fake_bw_usage(
time=self.expected_bw_usage['last_refreshed'],
start_period=self.expected_bw_usage['start_period'],
last_ctr_in=42, last_ctr_out=42)
bw_usage = bandwidth_usage.BandwidthUsage(context=self.context)
bw_usage.create(uuids.instance, 'fake_mac1',
100, 200, 42, 42,
start_period=self.expected_bw_usage['start_period'])
self._compare(self, expected_bw_usage1, bw_usage,
ignored_fields=['last_refreshed', 'created_at'])
bw_usage.create(uuids.instance, 'fake_mac1',
100, 200, 12345, 67890,
start_period=self.expected_bw_usage['start_period'])
self._compare(self, self.expected_bw_usage, bw_usage,
ignored_fields=['last_refreshed', 'created_at', 'updated_at'])
@mock.patch.object(db, 'bw_usage_update')
def test_update(self, mock_update):
expected_bw_usage1 = self._fake_bw_usage(
time=self.expected_bw_usage['last_refreshed'],
start_period=self.expected_bw_usage['start_period'],
last_ctr_in=42, last_ctr_out=42)
mock_update.side_effect = [expected_bw_usage1, self.expected_bw_usage]
bw_usage = bandwidth_usage.BandwidthUsage(context=self.context)
bw_usage.create('fake_uuid1', 'fake_mac1',
100, 200, 42, 42,
start_period=self.expected_bw_usage['start_period'])
self._compare(self, expected_bw_usage1, bw_usage)
bw_usage.create('fake_uuid1', 'fake_mac1',
100, 200, 12345, 67890,
start_period=self.expected_bw_usage['start_period'])
self._compare(self, self.expected_bw_usage, bw_usage)
class TestBandwidthUsageObject(test_objects._LocalTest,
_TestBandwidthUsage):
pass
class TestRemoteBandwidthUsageObject(test_objects._RemoteTest,
_TestBandwidthUsage):
pass
-2
View File
@@ -1046,8 +1046,6 @@ class TestRegistry(test.NoDBTestCase):
object_data = {
'Aggregate': '1.3-f315cb68906307ca2d1cca84d4753585',
'AggregateList': '1.3-3ea55a050354e72ef3306adefa553957',
'BandwidthUsage': '1.2-c6e4c779c7f40f2407e3d70022e3cd1c',
'BandwidthUsageList': '1.2-5fe7475ada6fe62413cbfcc06ec70746',
'BlockDeviceMapping': '1.20-45a6ad666ddf14bbbedece2293af77e2',
'BlockDeviceMappingList': '1.18-73bcbbae5ef5e8adcedbc821db869306',
'BuildRequest': '1.3-077dee42bed93f8a5b62be77657b7152',
-3
View File
@@ -263,9 +263,6 @@ class NotificationsTestCase(test.TestCase):
self.assertEqual(actual_ip['version'], expected_ip['version'])
self.assertEqual(actual_ip['address'], expected_ip['address'])
bandwidth = payload['bandwidth']
self.assertEqual(0, len(bandwidth))
def test_task_update_with_states(self):
self.flags(notify_on_state_change="vm_and_task_state",
group='notifications')
@@ -0,0 +1,9 @@
---
upgrade:
- |
The ``bandwidth`` field has been removed from the ``instance.exists`` and
``instance.update`` versioned notifications and the version for both
notifications has been bumped to 2.0. The ``bandwidth`` field was only
relevant when the XenAPI virt driver was in use, but this driver was
removed in the Victoria (22.0.0) release and the field has been a no-op
since.