def test_task_notif(self): # test config disable of just the task state notifications self.flags(notify_on_state_change="vm_state") # we should not get a notification on task stgate chagne now old = copy.copy(self.instance) self.instance.task_state = task_states.SPAWNING old_vm_state = old['vm_state'] new_vm_state = self.instance.vm_state old_task_state = old['task_state'] new_task_state = self.instance.task_state notifications.send_update_with_states(self.context, self.instance, old_vm_state, new_vm_state, old_task_state, new_task_state, verify_states=True) self.assertEqual(0, len(fake_notifier.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))
def test_fail_sending_update(self): def fail_sending(context, instance, **kwargs): raise Exception('failed to notify') self.stubs.Set(notifications, '_send_instance_update_notification', fail_sending) notifications.send_update(self.context, self.instance, self.instance) self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
def test_send_on_task_change(self): old = obj_base.obj_to_primitive(self.instance) old['task_state'] = None # pretend we just transitioned to task SPAWNING: self.instance.task_state = task_states.SPAWNING notifications.send_update(self.context, old, self.instance) self.assertEqual(1, len(fake_notifier.NOTIFICATIONS))
def test_send_no_state_change(self): called = [False] def sending_no_state_change(context, instance, **kwargs): called[0] = True self.stubs.Set(notifications, '_send_instance_update_notification', sending_no_state_change) notifications.send_update(self.context, self.instance, self.instance) self.assertTrue(called[0])
def test_send_access_ip_update(self): notifications.send_update(self.context, self.instance, self.instance) 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) self.assertEqual(payload["access_ip_v4"], access_ip_v4) self.assertEqual(payload["access_ip_v6"], access_ip_v6)
def test_send_on_vm_change(self): old = obj_base.obj_to_primitive(self.instance) old['vm_state'] = None # pretend we just transitioned to ACTIVE: self.instance.vm_state = vm_states.ACTIVE notifications.send_update(self.context, old, self.instance) self.assertEqual(1, len(fake_notifier.NOTIFICATIONS)) # service name should default to 'compute' notif = fake_notifier.NOTIFICATIONS[0] self.assertEqual('compute.testhost', notif.publisher_id)
def test_send_name_update(self): param = {"display_name": "new_display_name"} 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 old_display_name = self.instance.display_name new_display_name = new_name_inst.display_name self.assertEqual(payload["old_display_name"], old_display_name) self.assertEqual(payload["display_name"], new_display_name)
def test_set_vm_state_and_notify(self): expected_uuid = 'fake-uuid' request_spec = dict(instance_properties=dict(uuid='other-uuid')) updates = dict(vm_state='fake-vm-state') service = 'fake-service' method = 'fake-method' exc_info = 'exc_info' self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc') self.mox.StubOutWithMock(notifications, 'send_update') self.mox.StubOutWithMock(db, 'instance_update_and_get_original') self.mox.StubOutWithMock(rpc, 'get_notifier') notifier = self.mox.CreateMockAnything() rpc.get_notifier(service).AndReturn(notifier) old_ref = 'old_ref' new_ref = 'new_ref' inst_obj = 'inst_obj' db.instance_update_and_get_original( self.context, expected_uuid, updates, columns_to_join=['system_metadata']).AndReturn((old_ref, new_ref)) notifications.send_update(self.context, old_ref, inst_obj, service=service) compute_utils.add_instance_fault_from_exc( self.context, inst_obj, exc_info, mox.IsA(tuple)) payload = dict(request_spec=request_spec, instance_properties=request_spec.get( 'instance_properties', {}), instance_id=expected_uuid, state='fake-vm-state', method=method, reason=exc_info) event_type = '%s.%s' % (service, method) notifier.error(self.context, event_type, payload) self.mox.ReplayAll() with mock.patch.object(objects.Instance, '_from_db_object', return_value=inst_obj): scheduler_utils.set_vm_state_and_notify(self.context, expected_uuid, service, method, updates, exc_info, request_spec, db)
def test_set_vm_state_and_notify(self): expected_uuid = 'fake-uuid' request_spec = dict(instance_properties=dict(uuid='other-uuid')) updates = dict(vm_state='fake-vm-state') service = 'fake-service' method = 'fake-method' exc_info = 'exc_info' self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc') self.mox.StubOutWithMock(notifications, 'send_update') self.mox.StubOutWithMock(db, 'instance_update_and_get_original') self.mox.StubOutWithMock(rpc, 'get_notifier') notifier = self.mox.CreateMockAnything() rpc.get_notifier(service).AndReturn(notifier) old_ref = 'old_ref' new_ref = 'new_ref' inst_obj = 'inst_obj' db.instance_update_and_get_original( self.context, expected_uuid, updates, columns_to_join=['system_metadata']).AndReturn((old_ref, new_ref)) notifications.send_update(self.context, old_ref, inst_obj, service=service) compute_utils.add_instance_fault_from_exc(self.context, inst_obj, exc_info, mox.IsA(tuple)) payload = dict(request_spec=request_spec, instance_properties=request_spec.get( 'instance_properties', {}), instance_id=expected_uuid, state='fake-vm-state', method=method, reason=exc_info) event_type = '%s.%s' % (service, method) notifier.error(self.context, event_type, payload) self.mox.ReplayAll() with mock.patch.object(objects.Instance, '_from_db_object', return_value=inst_obj): scheduler_utils.set_vm_state_and_notify(self.context, expected_uuid, service, method, updates, exc_info, request_spec, db)
def set_vm_state_and_notify(context, instance_uuid, service, method, updates, ex, request_spec, db): """changes VM state and notifies.""" LOG.warning(_LW("Failed to %(service)s_%(method)s: %(ex)s"), { 'service': service, 'method': method, 'ex': ex }) vm_state = updates['vm_state'] properties = request_spec.get('instance_properties', {}) # NOTE(vish): We shouldn't get here unless we have a catastrophic # failure, so just set the instance to its internal state notifier = rpc.get_notifier(service) state = vm_state.upper() LOG.warning(_LW('Setting instance to %s state.'), state, instance_uuid=instance_uuid) # update instance state and notify on the transition # NOTE(hanlind): the send_update() call below is going to want to # know about the flavor, so we need to join the appropriate things # here and objectify the results. (old_ref, new_ref) = db.instance_update_and_get_original( context, instance_uuid, updates, columns_to_join=['system_metadata']) inst_obj = objects.Instance._from_db_object( context, objects.Instance(), new_ref, expected_attrs=['system_metadata']) notifications.send_update(context, old_ref, inst_obj, service=service) compute_utils.add_instance_fault_from_exc(context, inst_obj, ex, sys.exc_info()) payload = dict(request_spec=request_spec, instance_properties=properties, instance_id=instance_uuid, state=vm_state, method=method, reason=ex) event_type = '%s.%s' % (service, method) notifier.error(context, event_type, payload)
def test_notif_disabled(self): # test config disable of the notifications self.flags(notify_on_state_change=None) old = copy.copy(self.instance) self.instance.vm_state = vm_states.ACTIVE old_vm_state = old['vm_state'] new_vm_state = self.instance.vm_state old_task_state = old['task_state'] new_task_state = self.instance.task_state notifications.send_update_with_states(self.context, self.instance, old_vm_state, new_vm_state, old_task_state, new_task_state, verify_states=True) notifications.send_update(self.context, old, self.instance) self.assertEqual(0, len(fake_notifier.NOTIFICATIONS))
def instance_update(self, context, instance_uuid, updates, service): for key, value in updates.iteritems(): if key not in allowed_updates: LOG.error( _LE("Instance update attempted for " "'%(key)s' on %(instance_uuid)s"), {"key": key, "instance_uuid": instance_uuid}, ) raise KeyError("unexpected update keyword '%s'" % key) if key in datetime_fields and isinstance(value, six.string_types): updates[key] = timeutils.parse_strtime(value) # NOTE(danms): the send_update() call below is going to want to know # about the flavor, so we need to join the appropriate things here, # and objectify the result. old_ref, instance_ref = self.db.instance_update_and_get_original( context, instance_uuid, updates, columns_to_join=["system_metadata"] ) inst_obj = objects.Instance._from_db_object( context, objects.Instance(), instance_ref, expected_attrs=["system_metadata"] ) notifications.send_update(context, old_ref, inst_obj, service) return jsonutils.to_primitive(instance_ref)
def instance_update(self, context, instance_uuid, updates, service): for key, value in updates.iteritems(): if key not in allowed_updates: LOG.error(_LE("Instance update attempted for " "'%(key)s' on %(instance_uuid)s"), {'key': key, 'instance_uuid': instance_uuid}) raise KeyError("unexpected update keyword '%s'" % key) if key in datetime_fields and isinstance(value, six.string_types): updates[key] = timeutils.parse_strtime(value) # NOTE(danms): the send_update() call below is going to want to know # about the flavor, so we need to join the appropriate things here, # and objectify the result. old_ref, instance_ref = self.db.instance_update_and_get_original( context, instance_uuid, updates, columns_to_join=['system_metadata']) inst_obj = objects.Instance._from_db_object( context, objects.Instance(), instance_ref, expected_attrs=['system_metadata']) notifications.send_update(context, old_ref, inst_obj, service) return jsonutils.to_primitive(instance_ref)