Merge "Transform instance.update notification"
This commit is contained in:
commit
4e62960722
65
doc/notification_samples/instance-update.json
Normal file
65
doc/notification_samples/instance-update.json
Normal file
@ -0,0 +1,65 @@
|
||||
{
|
||||
"event_type": "instance.update",
|
||||
"payload": {
|
||||
"nova_object.data": {
|
||||
"architecture": "x86_64",
|
||||
"audit_period": {
|
||||
"nova_object.data": {
|
||||
"audit_period_beginning": "2012-10-01T00:00:00Z",
|
||||
"audit_period_ending": "2012-10-29T13:42:11Z"},
|
||||
"nova_object.name": "AuditPeriodPayload",
|
||||
"nova_object.namespace": "nova",
|
||||
"nova_object.version": "1.0"
|
||||
},
|
||||
"availability_zone": null,
|
||||
"bandwidth": [],
|
||||
"created_at": "2012-10-29T13:42:11Z",
|
||||
"deleted_at": null,
|
||||
"display_name": "some-server",
|
||||
"host": "compute",
|
||||
"host_name": "some-server",
|
||||
"image_uuid": "155d900f-4e14-4e4c-a73d-069cbf4541e6",
|
||||
"kernel_id": "",
|
||||
"launched_at": null,
|
||||
"metadata": {},
|
||||
"node": "fake-mini",
|
||||
"old_display_name": null,
|
||||
"os_type": null,
|
||||
"progress": 0,
|
||||
"ramdisk_id": "",
|
||||
"reservation_id": "r-sd3ygfjj",
|
||||
"state": "building",
|
||||
"task_state": "scheduling",
|
||||
"power_state": "pending",
|
||||
"ip_addresses": [],
|
||||
"state_update": {
|
||||
"nova_object.data": {
|
||||
"new_task_state": null,
|
||||
"old_state": "building",
|
||||
"old_task_state": null,
|
||||
"state": "building"},
|
||||
"nova_object.name": "InstanceStateUpdatePayload",
|
||||
"nova_object.namespace": "nova",
|
||||
"nova_object.version": "1.0"},
|
||||
"tenant_id": "6f70656e737461636b20342065766572",
|
||||
"terminated_at": null,
|
||||
"flavor": {
|
||||
"nova_object.name": "FlavorPayload",
|
||||
"nova_object.data": {
|
||||
"flavorid": "a22d5517-147c-4147-a0d1-e698df5cd4e3",
|
||||
"root_gb": 1,
|
||||
"vcpus": 1,
|
||||
"ephemeral_gb": 0,
|
||||
"memory_mb": 512
|
||||
},
|
||||
"nova_object.version": "1.0",
|
||||
"nova_object.namespace": "nova"
|
||||
},
|
||||
"user_id": "fake",
|
||||
"uuid": "c03c0bf9-f46e-4e4f-93f1-817568567ee2"},
|
||||
"nova_object.name": "InstanceUpdatePayload",
|
||||
"nova_object.namespace": "nova",
|
||||
"nova_object.version": "1.0"},
|
||||
"priority": "INFO",
|
||||
"publisher_id": "nova-compute:fake-mini"
|
||||
}
|
@ -33,11 +33,15 @@ from nova.i18n import _LE
|
||||
from nova.image import glance
|
||||
from nova import network
|
||||
from nova.network import model as network_model
|
||||
from nova.notifications.objects import base as notification_base
|
||||
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 import rpc
|
||||
from nova import utils
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
@ -244,6 +248,61 @@ def _send_instance_update_notification(context, instance, old_vm_state=None,
|
||||
rpc.get_notifier(service, host).info(context,
|
||||
'compute.instance.update', payload)
|
||||
|
||||
_send_versioned_instance_update(context, instance, payload, host, service)
|
||||
|
||||
|
||||
def _map_service_to_binary(service):
|
||||
if service == 'api':
|
||||
binary = 'nova-api'
|
||||
elif service == 'compute':
|
||||
binary = 'nova-compute'
|
||||
else:
|
||||
binary = service
|
||||
return binary
|
||||
|
||||
|
||||
def _send_versioned_instance_update(context, instance, payload, host, service):
|
||||
|
||||
state_update = instance_notification.InstanceStateUpdatePayload(
|
||||
old_state=payload.get('old_state'),
|
||||
state=payload.get('state'),
|
||||
old_task_state=payload.get('old_task_state'),
|
||||
new_task_state=payload.get('new_task_state'))
|
||||
|
||||
audit_period = instance_notification.AuditPeriodPayload(
|
||||
audit_period_beginning=payload.get('audit_period_beginning'),
|
||||
audit_period_ending=payload.get('audit_period_ending'))
|
||||
|
||||
bandwidth = [instance_notification.BandwidthPayload(
|
||||
network_name=label,
|
||||
in_bytes=bw['bw_in'],
|
||||
out_bytes=bw['bw_out'])
|
||||
for label, bw in payload['bandwidth'].items()]
|
||||
|
||||
network_info = instance.info_cache.network_info
|
||||
flavor = instance_notification.FlavorPayload(instance=instance)
|
||||
|
||||
versioned_payload = instance_notification.InstanceUpdatePayload(
|
||||
instance=instance,
|
||||
state_update=state_update,
|
||||
audit_period=audit_period,
|
||||
bandwidth=bandwidth,
|
||||
ip_addresses=instance_notification.IpPayload.from_network_info(
|
||||
network_info),
|
||||
flavor=flavor,
|
||||
old_display_name=payload.get('old_display_name'))
|
||||
|
||||
notification = instance_notification.InstanceUpdateNotification(
|
||||
priority=fields.NotificationPriority.INFO,
|
||||
event_type=notification_base.EventType(
|
||||
object='instance',
|
||||
action=fields.NotificationAction.UPDATE),
|
||||
publisher=notification_base.NotificationPublisher(
|
||||
host=host or CONF.host,
|
||||
binary=_map_service_to_binary(service)),
|
||||
payload=versioned_payload)
|
||||
notification.emit(context)
|
||||
|
||||
|
||||
def audit_period_bounds(current_period=False):
|
||||
"""Get the start and end of the relevant audit usage period
|
||||
|
@ -105,6 +105,29 @@ class InstanceActionPayload(InstancePayload):
|
||||
flavor=flavor)
|
||||
|
||||
|
||||
@nova_base.NovaObjectRegistry.register_notification
|
||||
class InstanceUpdatePayload(InstancePayload):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
fields = {
|
||||
'state_update': fields.ObjectField('InstanceStateUpdatePayload'),
|
||||
'audit_period': fields.ObjectField('AuditPeriodPayload'),
|
||||
'bandwidth': fields.ListOfObjectsField('BandwidthPayload'),
|
||||
'old_display_name': fields.StringField(nullable=True)
|
||||
}
|
||||
|
||||
def __init__(self, instance, flavor, ip_addresses, state_update,
|
||||
audit_period, bandwidth, old_display_name):
|
||||
super(InstanceUpdatePayload, self).__init__(
|
||||
instance=instance,
|
||||
flavor=flavor,
|
||||
ip_addresses=ip_addresses,
|
||||
state_update=state_update,
|
||||
audit_period=audit_period,
|
||||
bandwidth=bandwidth,
|
||||
old_display_name=old_display_name)
|
||||
|
||||
|
||||
@nova_base.NovaObjectRegistry.register_notification
|
||||
class IpPayload(base.NotificationPayloadBase):
|
||||
# Version 1.0: Initial version
|
||||
@ -119,6 +142,25 @@ class IpPayload(base.NotificationPayloadBase):
|
||||
'device_name': fields.StringField(nullable=True)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_network_info(cls, network_info):
|
||||
"""Returns a list of IpPayload object based on the passed
|
||||
network_info.
|
||||
"""
|
||||
ips = []
|
||||
if network_info is not None:
|
||||
for vif in network_info:
|
||||
for ip in vif.fixed_ips():
|
||||
ips.append(cls(
|
||||
label=vif["network"]["label"],
|
||||
mac=vif["address"],
|
||||
meta=vif["meta"],
|
||||
port_uuid=vif["id"],
|
||||
version=ip["version"],
|
||||
address=ip["address"],
|
||||
device_name=vif["devname"]))
|
||||
return ips
|
||||
|
||||
|
||||
@nova_base.NovaObjectRegistry.register_notification
|
||||
class FlavorPayload(base.NotificationPayloadBase):
|
||||
@ -146,6 +188,39 @@ class FlavorPayload(base.NotificationPayloadBase):
|
||||
self.populate_schema(instance=instance, flavor=instance.flavor)
|
||||
|
||||
|
||||
@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(),
|
||||
}
|
||||
|
||||
|
||||
@nova_base.NovaObjectRegistry.register_notification
|
||||
class AuditPeriodPayload(base.NotificationPayloadBase):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
fields = {
|
||||
'audit_period_beginning': fields.DateTimeField(),
|
||||
'audit_period_ending': fields.DateTimeField(),
|
||||
}
|
||||
|
||||
|
||||
@nova_base.NovaObjectRegistry.register_notification
|
||||
class InstanceStateUpdatePayload(base.NotificationPayloadBase):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
fields = {
|
||||
'old_state': fields.StringField(nullable=True),
|
||||
'state': fields.StringField(nullable=True),
|
||||
'old_task_state': fields.StringField(nullable=True),
|
||||
'new_task_state': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
|
||||
@base.notification_sample('instance-delete-start.json')
|
||||
@base.notification_sample('instance-delete-end.json')
|
||||
# @base.notification_sample('instance-pause-start.json')
|
||||
@ -182,3 +257,14 @@ class InstanceActionNotification(base.NotificationBase):
|
||||
fields = {
|
||||
'payload': fields.ObjectField('InstanceActionPayload')
|
||||
}
|
||||
|
||||
|
||||
@base.notification_sample('instance-update.json')
|
||||
@nova_base.NovaObjectRegistry.register_notification
|
||||
class InstanceUpdateNotification(base.NotificationBase):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'payload': fields.ObjectField('InstanceUpdatePayload')
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class NotificationSampleTestBase(test.TestCase,
|
||||
self.start_service('conductor', manager=CONF.conductor.manager)
|
||||
self.start_service('scheduler')
|
||||
self.start_service('network')
|
||||
self.start_service('compute')
|
||||
self.compute = self.start_service('compute')
|
||||
|
||||
def _get_notification_sample(self, sample):
|
||||
sample_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
@ -177,3 +177,8 @@ class NotificationSampleTestBase(test.TestCase,
|
||||
self.fail('Server failed to delete.')
|
||||
except api_client.OpenStackApiNotFoundException:
|
||||
return
|
||||
|
||||
def _get_notifications(self, event_type):
|
||||
return [notification for notification
|
||||
in fake_notifier.VERSIONED_NOTIFICATIONS
|
||||
if notification['event_type'] == event_type]
|
||||
|
@ -9,6 +9,7 @@
|
||||
# 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 import context
|
||||
from nova.tests import fixtures
|
||||
from nova.tests.functional.notification_sample_tests \
|
||||
import notification_sample_base
|
||||
@ -47,3 +48,145 @@ class TestInstanceNotificationSample(
|
||||
notification_sample_base.NotificationSampleTestBase.ANY,
|
||||
'uuid': server['id']},
|
||||
actual=fake_notifier.VERSIONED_NOTIFICATIONS[1])
|
||||
|
||||
def _verify_instance_update_steps(self, steps, notifications,
|
||||
initial=None):
|
||||
replacements = {}
|
||||
if initial:
|
||||
replacements = initial
|
||||
for i, step in enumerate(steps):
|
||||
replacements.update(step)
|
||||
self._verify_notification(
|
||||
'instance-update',
|
||||
replacements=replacements,
|
||||
actual=notifications[i])
|
||||
return replacements
|
||||
|
||||
def test_create_delete_server_with_instance_update(self):
|
||||
self.flags(notify_on_state_change='vm_and_task_state')
|
||||
|
||||
server = self._boot_a_server(
|
||||
extra_params={'networks': [{'port': self.neutron.port_1['id']}]})
|
||||
|
||||
instance_updates = self._get_notifications('instance.update')
|
||||
|
||||
# The first notification comes from the nova-api the rest is from the
|
||||
# nova-compute. To keep the test simpler assert this fact and then
|
||||
# modify the publisher_id of the first notification to match the
|
||||
# template
|
||||
self.assertEqual('nova-api:fake-mini',
|
||||
instance_updates[0]['publisher_id'])
|
||||
instance_updates[0]['publisher_id'] = 'nova-compute:fake-mini'
|
||||
|
||||
self.assertEqual(7, len(instance_updates))
|
||||
create_steps = [
|
||||
# nothing -> scheduling
|
||||
{'reservation_id':
|
||||
notification_sample_base.NotificationSampleTestBase.ANY,
|
||||
'uuid': server['id'],
|
||||
'host': None,
|
||||
'node': None,
|
||||
'state_update.new_task_state': 'scheduling',
|
||||
'state_update.old_task_state': 'scheduling',
|
||||
'state_update.state': 'building',
|
||||
'state_update.old_state': 'building',
|
||||
'state': 'building'},
|
||||
|
||||
# scheduling -> building
|
||||
{
|
||||
'state_update.new_task_state': None,
|
||||
'state_update.old_task_state': 'scheduling',
|
||||
'task_state': None},
|
||||
|
||||
# scheduled
|
||||
{'host': 'compute',
|
||||
'node': 'fake-mini',
|
||||
'state_update.old_task_state': None},
|
||||
|
||||
# building -> networking
|
||||
{'state_update.new_task_state': 'networking',
|
||||
'state_update.old_task_state': 'networking',
|
||||
'task_state': 'networking'},
|
||||
|
||||
# networking -> block_device_mapping
|
||||
{'state_update.new_task_state': 'block_device_mapping',
|
||||
'state_update.old_task_state': 'networking',
|
||||
'task_state': 'block_device_mapping',
|
||||
},
|
||||
|
||||
# block_device_mapping -> spawning
|
||||
{'state_update.new_task_state': 'spawning',
|
||||
'state_update.old_task_state': 'block_device_mapping',
|
||||
'task_state': 'spawning',
|
||||
'ip_addresses': [{
|
||||
"nova_object.name": "IpPayload",
|
||||
"nova_object.namespace": "nova",
|
||||
"nova_object.version": "1.0",
|
||||
"nova_object.data": {
|
||||
"mac": "fa:16:3e:4c:2c:30",
|
||||
"address": "192.168.1.3",
|
||||
"port_uuid": "ce531f90-199f-48c0-816c-13e38010b442",
|
||||
"meta": {},
|
||||
"version": 4,
|
||||
"label": "private-network",
|
||||
"device_name": "tapce531f90-19"
|
||||
}}]
|
||||
},
|
||||
|
||||
# spawning -> active
|
||||
{'state_update.new_task_state': None,
|
||||
'state_update.old_task_state': 'spawning',
|
||||
'state_update.state': 'active',
|
||||
'launched_at': '2012-10-29T13:42:11Z',
|
||||
'state': 'active',
|
||||
'task_state': None,
|
||||
'power_state': 'running'},
|
||||
]
|
||||
|
||||
replacements = self._verify_instance_update_steps(
|
||||
create_steps, instance_updates)
|
||||
|
||||
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.api.delete_server(server['id'])
|
||||
self._wait_until_deleted(server)
|
||||
|
||||
instance_updates = self._get_notifications('instance.update')
|
||||
self.assertEqual(2, len(instance_updates))
|
||||
|
||||
delete_steps = [
|
||||
# active -> deleting
|
||||
{'state_update.new_task_state': 'deleting',
|
||||
'state_update.old_task_state': 'deleting',
|
||||
'state_update.old_state': 'active',
|
||||
'state': 'active',
|
||||
'task_state': 'deleting',
|
||||
'bandwidth': [
|
||||
{'nova_object.namespace': 'nova',
|
||||
'nova_object.name': 'BandwidthPayload',
|
||||
'nova_object.data':
|
||||
{'network_name': 'private-network',
|
||||
'out_bytes': 0,
|
||||
'in_bytes': 0},
|
||||
'nova_object.version': '1.0'}]
|
||||
},
|
||||
|
||||
# deleting -> deleted
|
||||
{'state_update.new_task_state': None,
|
||||
'state_update.old_task_state': 'deleting',
|
||||
'state_update.old_state': 'active',
|
||||
'state_update.state': 'deleted',
|
||||
'state': 'deleted',
|
||||
'task_state': None,
|
||||
'terminated_at': '2012-10-29T13:42:11Z',
|
||||
'ip_addresses': [],
|
||||
'power_state': 'pending',
|
||||
'bandwidth': []},
|
||||
]
|
||||
|
||||
self._verify_instance_update_steps(delete_steps, instance_updates,
|
||||
initial=replacements)
|
||||
|
@ -255,6 +255,8 @@ class TestNotificationBase(test.NoDBTestCase):
|
||||
|
||||
|
||||
notification_object_data = {
|
||||
'AuditPeriodPayload': '1.0-28345f72ca9d805eeb61b2c2385805dd',
|
||||
'BandwidthPayload': '1.0-49278639296f9939ff2c8947b2078a82',
|
||||
'EventType': '1.3-6ef678bfe9a4ebfd669c96d2d2c124a5',
|
||||
'ExceptionNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
|
||||
'ExceptionPayload': '1.0-4516ae282a55fe2fd5c754967ee6248b',
|
||||
@ -262,6 +264,9 @@ notification_object_data = {
|
||||
'InstanceActionNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
|
||||
'InstanceActionPayload': '1.0-aa6a322cf1a3a19d090259fee65d1094',
|
||||
'InstancePayload': '1.0-878bbc5a7a20bdeac7c6570f438a53aa',
|
||||
'InstanceStateUpdatePayload': '1.0-a934d04e1b314318e42e8062647edd11',
|
||||
'InstanceUpdateNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
|
||||
'InstanceUpdatePayload': '1.0-c69e17e00400455bfe602e5573a61f0b',
|
||||
'IpPayload': '1.0-26b40117c41ed95a61ae104f0fcb5fdc',
|
||||
'NotificationPublisher': '1.0-bbbc1402fb0e443a3eb227cc52b61545',
|
||||
'ServiceStatusNotification': '1.0-a73147b93b520ff0061865849d3dfa56',
|
||||
|
@ -200,6 +200,7 @@ class NotificationsTestCase(test.TestCase):
|
||||
|
||||
notifications.send_update(self.context, old, self.instance)
|
||||
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
|
||||
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
def test_task_notif(self):
|
||||
|
||||
@ -220,12 +221,18 @@ class NotificationsTestCase(test.TestCase):
|
||||
verify_states=True)
|
||||
|
||||
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
|
||||
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
# ok now enable task state notifications and re-try
|
||||
self.flags(notify_on_state_change="vm_and_task_state")
|
||||
|
||||
notifications.send_update(self.context, old, self.instance)
|
||||
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
self.assertEqual(
|
||||
'instance.update',
|
||||
fake_notifier.VERSIONED_NOTIFICATIONS[0]['event_type'])
|
||||
|
||||
def test_send_no_notif(self):
|
||||
|
||||
@ -240,6 +247,7 @@ class NotificationsTestCase(test.TestCase):
|
||||
service="compute", host=None, verify_states=True)
|
||||
|
||||
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
|
||||
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
def test_send_on_vm_change(self):
|
||||
old = obj_base.obj_to_primitive(self.instance)
|
||||
@ -253,6 +261,14 @@ class NotificationsTestCase(test.TestCase):
|
||||
notif = fake_notifier.NOTIFICATIONS[0]
|
||||
self.assertEqual('compute.testhost', notif.publisher_id)
|
||||
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
self.assertEqual(
|
||||
'nova-compute:testhost',
|
||||
fake_notifier.VERSIONED_NOTIFICATIONS[0]['publisher_id'])
|
||||
self.assertEqual(
|
||||
'instance.update',
|
||||
fake_notifier.VERSIONED_NOTIFICATIONS[0]['event_type'])
|
||||
|
||||
def test_send_on_task_change(self):
|
||||
|
||||
old = obj_base.obj_to_primitive(self.instance)
|
||||
@ -262,6 +278,10 @@ class NotificationsTestCase(test.TestCase):
|
||||
notifications.send_update(self.context, old, self.instance)
|
||||
|
||||
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
self.assertEqual(
|
||||
'instance.update',
|
||||
fake_notifier.VERSIONED_NOTIFICATIONS[0]['event_type'])
|
||||
|
||||
def test_no_update_with_states(self):
|
||||
|
||||
@ -269,84 +289,146 @@ class NotificationsTestCase(test.TestCase):
|
||||
vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING,
|
||||
task_states.SPAWNING, verify_states=True)
|
||||
self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
|
||||
self.assertEqual(0, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
def test_vm_update_with_states(self):
|
||||
def get_fake_bandwidth(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, 1, 1)
|
||||
self.instance.info_cache.network_info = fake_net_info
|
||||
|
||||
notifications.send_update_with_states(self.context, self.instance,
|
||||
vm_states.BUILDING, vm_states.ACTIVE, task_states.SPAWNING,
|
||||
task_states.SPAWNING, verify_states=True)
|
||||
|
||||
self._verify_notification()
|
||||
|
||||
def _verify_notification(self, expected_state=vm_states.ACTIVE,
|
||||
expected_new_task_state=task_states.SPAWNING):
|
||||
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
|
||||
notif = fake_notifier.NOTIFICATIONS[0]
|
||||
payload = notif.payload
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
self.assertEqual(
|
||||
'instance.update',
|
||||
fake_notifier.VERSIONED_NOTIFICATIONS[0]['event_type'])
|
||||
access_ip_v4 = str(self.instance.access_ip_v4)
|
||||
access_ip_v6 = str(self.instance.access_ip_v6)
|
||||
display_name = self.instance.display_name
|
||||
hostname = self.instance.hostname
|
||||
node = self.instance.node
|
||||
|
||||
payload = fake_notifier.NOTIFICATIONS[0].payload
|
||||
self.assertEqual(vm_states.BUILDING, payload["old_state"])
|
||||
self.assertEqual(vm_states.ACTIVE, payload["state"])
|
||||
self.assertEqual(expected_state, payload["state"])
|
||||
self.assertEqual(task_states.SPAWNING, payload["old_task_state"])
|
||||
self.assertEqual(task_states.SPAWNING, payload["new_task_state"])
|
||||
self.assertEqual(expected_new_task_state, payload["new_task_state"])
|
||||
self.assertEqual(payload["access_ip_v4"], access_ip_v4)
|
||||
self.assertEqual(payload["access_ip_v6"], access_ip_v6)
|
||||
self.assertEqual(payload["display_name"], display_name)
|
||||
self.assertEqual(payload["hostname"], hostname)
|
||||
self.assertEqual(payload["node"], node)
|
||||
payload = fake_notifier.VERSIONED_NOTIFICATIONS[0][
|
||||
'payload']['nova_object.data']
|
||||
state_update = payload['state_update']['nova_object.data']
|
||||
self.assertEqual(vm_states.BUILDING, state_update['old_state'])
|
||||
self.assertEqual(expected_state, state_update["state"])
|
||||
self.assertEqual(task_states.SPAWNING, state_update["old_task_state"])
|
||||
self.assertEqual(expected_new_task_state,
|
||||
state_update["new_task_state"])
|
||||
self.assertEqual(payload["display_name"], display_name)
|
||||
self.assertEqual(payload["host_name"], hostname)
|
||||
self.assertEqual(payload["node"], node)
|
||||
flavor = payload['flavor']['nova_object.data']
|
||||
self.assertEqual(flavor['flavorid'], '1')
|
||||
self.assertEqual(payload['image_uuid'], uuids.image_ref)
|
||||
|
||||
def test_task_update_with_states(self):
|
||||
net_info = self.instance.info_cache.network_info
|
||||
vif = net_info[0]
|
||||
ip_addresses = payload['ip_addresses']
|
||||
|
||||
self.assertEqual(len(ip_addresses), 2)
|
||||
for actual_ip, expected_ip in zip(ip_addresses, vif.fixed_ips()):
|
||||
actual_ip = actual_ip['nova_object.data']
|
||||
self.assertEqual(actual_ip['label'], vif['network']['label'])
|
||||
self.assertEqual(actual_ip['mac'], vif['address'].lower())
|
||||
self.assertEqual(actual_ip['port_uuid'], vif['id'])
|
||||
self.assertEqual(actual_ip['device_name'], vif['devname'])
|
||||
self.assertEqual(actual_ip['version'], expected_ip['version'])
|
||||
self.assertEqual(actual_ip['address'], expected_ip['address'])
|
||||
|
||||
bandwidth = payload['bandwidth']
|
||||
self.assertEqual(len(bandwidth), 1)
|
||||
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, mock_bandwidth_list):
|
||||
self.flags(notify_on_state_change="vm_and_task_state")
|
||||
mock_bandwidth_list.return_value = [self.get_fake_bandwidth()]
|
||||
fake_net_info = fake_network.fake_get_instance_nw_info(self, 1, 1)
|
||||
self.instance.info_cache.network_info = fake_net_info
|
||||
|
||||
notifications.send_update_with_states(self.context, self.instance,
|
||||
vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING,
|
||||
None, verify_states=True)
|
||||
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
|
||||
notif = fake_notifier.NOTIFICATIONS[0]
|
||||
payload = notif.payload
|
||||
access_ip_v4 = str(self.instance.access_ip_v4)
|
||||
access_ip_v6 = str(self.instance.access_ip_v6)
|
||||
display_name = self.instance.display_name
|
||||
hostname = self.instance.hostname
|
||||
|
||||
self.assertEqual(vm_states.BUILDING, payload["old_state"])
|
||||
self.assertEqual(vm_states.BUILDING, payload["state"])
|
||||
self.assertEqual(task_states.SPAWNING, payload["old_task_state"])
|
||||
self.assertIsNone(payload["new_task_state"])
|
||||
self.assertEqual(payload["access_ip_v4"], access_ip_v4)
|
||||
self.assertEqual(payload["access_ip_v6"], access_ip_v6)
|
||||
self.assertEqual(payload["display_name"], display_name)
|
||||
self.assertEqual(payload["hostname"], hostname)
|
||||
self._verify_notification(expected_state=vm_states.BUILDING,
|
||||
expected_new_task_state=None)
|
||||
|
||||
def test_update_no_service_name(self):
|
||||
notifications.send_update_with_states(self.context, self.instance,
|
||||
vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING,
|
||||
None)
|
||||
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
# service name should default to 'compute'
|
||||
notif = fake_notifier.NOTIFICATIONS[0]
|
||||
self.assertEqual('compute.testhost', notif.publisher_id)
|
||||
|
||||
# in the versioned notification it defaults to nova-compute
|
||||
notif = fake_notifier.VERSIONED_NOTIFICATIONS[0]
|
||||
self.assertEqual('nova-compute:testhost', notif['publisher_id'])
|
||||
|
||||
def test_update_with_service_name(self):
|
||||
notifications.send_update_with_states(self.context, self.instance,
|
||||
vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING,
|
||||
None, service="testservice")
|
||||
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
# service name should default to 'compute'
|
||||
notif = fake_notifier.NOTIFICATIONS[0]
|
||||
self.assertEqual('testservice.testhost', notif.publisher_id)
|
||||
|
||||
notif = fake_notifier.VERSIONED_NOTIFICATIONS[0]
|
||||
self.assertEqual('testservice:testhost', notif['publisher_id'])
|
||||
|
||||
def test_update_with_host_name(self):
|
||||
notifications.send_update_with_states(self.context, self.instance,
|
||||
vm_states.BUILDING, vm_states.BUILDING, task_states.SPAWNING,
|
||||
None, host="someotherhost")
|
||||
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
# service name should default to 'compute'
|
||||
notif = fake_notifier.NOTIFICATIONS[0]
|
||||
self.assertEqual('compute.someotherhost', notif.publisher_id)
|
||||
|
||||
notif = fake_notifier.VERSIONED_NOTIFICATIONS[0]
|
||||
self.assertEqual('nova-compute:someotherhost', notif['publisher_id'])
|
||||
|
||||
def test_payload_has_fixed_ip_labels(self):
|
||||
info = notifications.info_from_instance(self.context, self.instance,
|
||||
self.net_info, None)
|
||||
@ -404,11 +486,16 @@ class NotificationsTestCase(test.TestCase):
|
||||
new_name_inst = self._wrapped_create(params=param)
|
||||
notifications.send_update(self.context, self.instance, new_name_inst)
|
||||
self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
|
||||
notif = fake_notifier.NOTIFICATIONS[0]
|
||||
payload = notif.payload
|
||||
self.assertEqual(1, len(fake_notifier.VERSIONED_NOTIFICATIONS))
|
||||
|
||||
old_display_name = self.instance.display_name
|
||||
new_display_name = new_name_inst.display_name
|
||||
|
||||
for payload in [
|
||||
fake_notifier.NOTIFICATIONS[0].payload,
|
||||
fake_notifier.VERSIONED_NOTIFICATIONS[0][
|
||||
'payload']['nova_object.data']]:
|
||||
|
||||
self.assertEqual(payload["old_display_name"], old_display_name)
|
||||
self.assertEqual(payload["display_name"], new_display_name)
|
||||
|
||||
|
@ -367,6 +367,11 @@ class FakeDriver(driver.ComputeDriver):
|
||||
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):
|
||||
|
Loading…
Reference in New Issue
Block a user