Example #1
0
    def test_events(self):
        got_events = []

        def handler(event):
            got_events.append(event)

        self.connection.register_event_listener(handler)

        event1 = virtevent.LifecycleEvent(
            "cef19ce0-0ca2-11df-855d-b19fbce37686",
            virtevent.EVENT_LIFECYCLE_STARTED)
        event2 = virtevent.LifecycleEvent(
            "cef19ce0-0ca2-11df-855d-b19fbce37686",
            virtevent.EVENT_LIFECYCLE_PAUSED)

        self.connection.emit_event(event1)
        self.connection.emit_event(event2)
        want_events = [event1, event2]
        self.assertEqual(want_events, got_events)

        event3 = virtevent.LifecycleEvent(
            "cef19ce0-0ca2-11df-855d-b19fbce37686",
            virtevent.EVENT_LIFECYCLE_RESUMED)
        event4 = virtevent.LifecycleEvent(
            "cef19ce0-0ca2-11df-855d-b19fbce37686",
            virtevent.EVENT_LIFECYCLE_STOPPED)

        self.connection.emit_event(event3)
        self.connection.emit_event(event4)

        want_events = [event1, event2, event3, event4]
        self.assertEqual(want_events, got_events)
Example #2
0
    def test_event_dispatch(self):
        # Validate that the libvirt self-pipe for forwarding
        # events between threads is working sanely
        def handler(event):
            got_events.append(event)

        hostimpl = host.Host("qemu:///system", lifecycle_event_handler=handler)
        got_events = []

        hostimpl._init_events_pipe()

        event1 = event.LifecycleEvent("cef19ce0-0ca2-11df-855d-b19fbce37686",
                                      event.EVENT_LIFECYCLE_STARTED)
        event2 = event.LifecycleEvent("cef19ce0-0ca2-11df-855d-b19fbce37686",
                                      event.EVENT_LIFECYCLE_PAUSED)
        hostimpl._queue_event(event1)
        hostimpl._queue_event(event2)
        hostimpl._dispatch_events()

        want_events = [event1, event2]
        self.assertEqual(want_events, got_events)

        event3 = event.LifecycleEvent("cef19ce0-0ca2-11df-855d-b19fbce37686",
                                      event.EVENT_LIFECYCLE_RESUMED)
        event4 = event.LifecycleEvent("cef19ce0-0ca2-11df-855d-b19fbce37686",
                                      event.EVENT_LIFECYCLE_STOPPED)

        hostimpl._queue_event(event3)
        hostimpl._queue_event(event4)
        hostimpl._dispatch_events()

        want_events = [event1, event2, event3, event4]
        self.assertEqual(want_events, got_events)
Example #3
0
    def _event_lifecycle_callback(conn, dom, event, detail, opaque):
        """Receives lifecycle events from libvirt.

        NB: this method is executing in a native thread, not
        an eventlet coroutine. It can only invoke other libvirt
        APIs, or use self._queue_event(). Any use of logging APIs
        in particular is forbidden.
        """

        self = opaque

        uuid = dom.UUIDString()
        transition = None
        if event == libvirt.VIR_DOMAIN_EVENT_STOPPED:
            # WRS: transition to crashed if stop failed
            if detail == libvirt.VIR_DOMAIN_EVENT_STOPPED_FAILED:
                transition = virtevent.EVENT_LIFECYCLE_CRASHED
            else:
                transition = virtevent.EVENT_LIFECYCLE_STOPPED
        elif event == libvirt.VIR_DOMAIN_EVENT_STARTED:
            transition = virtevent.EVENT_LIFECYCLE_STARTED
        elif event == libvirt.VIR_DOMAIN_EVENT_SUSPENDED:
            transition = virtevent.EVENT_LIFECYCLE_PAUSED
        elif event == libvirt.VIR_DOMAIN_EVENT_RESUMED:
            transition = virtevent.EVENT_LIFECYCLE_RESUMED

        if transition is not None:
            self._queue_event(virtevent.LifecycleEvent(uuid, transition))
Example #4
0
    def _event_lifecycle_callback(conn, dom, event, detail, opaque):
        """Receives lifecycle events from libvirt.

        NB: this method is executing in a native thread, not
        an eventlet coroutine. It can only invoke other libvirt
        APIs, or use self._queue_event(). Any use of logging APIs
        in particular is forbidden.
        """

        self = opaque

        uuid = dom.UUIDString()
        transition = None
        if event == libvirt.VIR_DOMAIN_EVENT_STOPPED:
            transition = virtevent.EVENT_LIFECYCLE_STOPPED
        elif event == libvirt.VIR_DOMAIN_EVENT_STARTED:
            transition = virtevent.EVENT_LIFECYCLE_STARTED
        elif event == libvirt.VIR_DOMAIN_EVENT_SUSPENDED:
            if detail == libvirt.VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY:
                transition = virtevent.EVENT_LIFECYCLE_POSTCOPY_STARTED
            # FIXME(mriedem): VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED is also sent
            # when live migration of the guest fails, so we cannot simply rely
            # on the event itself but need to check if the job itself was
            # successful.
            # elif detail == libvirt.VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED:
            #     transition = virtevent.EVENT_LIFECYCLE_MIGRATION_COMPLETED
            else:
                transition = virtevent.EVENT_LIFECYCLE_PAUSED
        elif event == libvirt.VIR_DOMAIN_EVENT_RESUMED:
            transition = virtevent.EVENT_LIFECYCLE_RESUMED

        if transition is not None:
            self._queue_event(virtevent.LifecycleEvent(uuid, transition))
Example #5
0
    def _emit_event(self, pvm_state, inst, is_immed):
        if is_immed:
            # Cancel out any delayed events
            cancel_thread = self._delayed_event_threads.get(inst.uuid)
            if cancel_thread:
                cancel_thread.cancel()
                del self._delayed_event_threads[inst.uuid]
        else:
            # Make sure you're still in the thread.  If not (thread was started
            # but the is_immed _emit_event had run the del), then just bail
            inst_queue = self._delayed_event_threads.get(inst.uuid)
            if not inst_queue:
                return

        # See if it's really a change of state from what OpenStack knows
        transition = vm.translate_event(pvm_state, inst.power_state)
        if transition is None:
            return

        # Log as if normal event
        lce = event.LifecycleEvent(inst.uuid, transition)
        LOG.info(_LI('Sending life cycle event for instance state '
                     'change to: %s'),
                 pvm_state,
                 instance=inst)
        self._driver.emit_event(lce)

        if not is_immed:
            # Delete out the queue
            del self._delayed_event_threads[inst.uuid]
Example #6
0
 def test_event_emit_delayed_call_delayed(self, spawn_after_mock):
     hostimpl = host.Host("xen:///",
                          lifecycle_event_handler=lambda e: None)
     ev = event.LifecycleEvent(
         "cef19ce0-0ca2-11df-855d-b19fbce37686",
         event.EVENT_LIFECYCLE_STOPPED)
     hostimpl._event_emit_delayed(ev)
     spawn_after_mock.assert_called_once_with(15, hostimpl._event_emit, ev)
Example #7
0
    def test_event_emit_delayed_call_delayed_pending(self, spawn_after_mock):
        hostimpl = host.Host("xen:///", lifecycle_event_handler=lambda e: None)

        uuid = "cef19ce0-0ca2-11df-855d-b19fbce37686"
        hostimpl._events_delayed[uuid] = None
        ev = event.LifecycleEvent(uuid, event.EVENT_LIFECYCLE_STOPPED)
        hostimpl._event_emit_delayed(ev)
        self.assertFalse(spawn_after_mock.called)
Example #8
0
 def test_event_delayed_cleanup(self):
     hostimpl = host.Host("xen:///", lifecycle_event_handler=lambda e: None)
     uuid = "cef19ce0-0ca2-11df-855d-b19fbce37686"
     ev = event.LifecycleEvent(uuid, event.EVENT_LIFECYCLE_STARTED)
     gt_mock = mock.Mock()
     hostimpl._events_delayed[uuid] = gt_mock
     hostimpl._event_emit_delayed(ev)
     gt_mock.cancel.assert_called_once_with()
     self.assertNotIn(uuid, hostimpl._events_delayed.keys())
Example #9
0
 def test_event_emit_delayed_call_delayed(self):
     ev = event.LifecycleEvent("cef19ce0-0ca2-11df-855d-b19fbce37686",
                               event.EVENT_LIFECYCLE_STOPPED)
     for uri in ("qemu:///system", "xen:///"):
         spawn_after_mock = mock.Mock()
         greenthread.spawn_after = spawn_after_mock
         hostimpl = host.Host(uri, lifecycle_event_handler=lambda e: None)
         hostimpl._event_emit_delayed(ev)
         spawn_after_mock.assert_called_once_with(15, hostimpl._event_emit,
                                                  ev)
 def test_emit_unicode_event(self):
     """Tests that we do not fail on translated unicode events."""
     started_event = virtevent.LifecycleEvent(
         "cef19ce0-0ca2-11df-855d-b19fbce37686",
         virtevent.EVENT_LIFECYCLE_STARTED)
     callback = mock.Mock()
     self.connection.register_event_listener(callback)
     with mock.patch.object(started_event, 'get_name',
                            return_value=u'\xF0\x9F\x92\xA9'):
         self.connection.emit_event(started_event)
     callback.assert_called_once_with(started_event)
Example #11
0
    def test_event_emit_delayed_call_now(self):
        got_events = []

        def handler(event):
            got_events.append(event)

        hostimpl = host.Host("qemu:///system", lifecycle_event_handler=handler)
        ev = event.LifecycleEvent("cef19ce0-0ca2-11df-855d-b19fbce37686",
                                  event.EVENT_LIFECYCLE_STOPPED)
        hostimpl._event_emit_delayed(ev)
        self.assertEqual(1, len(got_events))
        self.assertEqual(ev, got_events[0])
    def test_event_repr(self):
        t = time.time()
        uuid = '1234'
        lifecycle = event.EVENT_LIFECYCLE_RESUMED

        e = event.Event(t)
        self.assertEqual(str(e), "<Event: %s>" % t)

        e = event.InstanceEvent(uuid, timestamp=t)
        self.assertEqual(str(e), "<InstanceEvent: %s, %s>" % (t, uuid))

        e = event.LifecycleEvent(uuid, lifecycle, timestamp=t)
        self.assertEqual(str(e),
                         "<LifecycleEvent: %s, %s => Resumed>" % (t, uuid))
Example #13
0
    def _event_lifecycle_callback(conn, dom, event, detail, opaque):
        """Receives lifecycle events from libvirt.

        NB: this method is executing in a native thread, not
        an eventlet coroutine. It can only invoke other libvirt
        APIs, or use self._queue_event(). Any use of logging APIs
        in particular is forbidden.
        """

        self = opaque

        uuid = dom.UUIDString()
        transition = None
        if event == libvirt.VIR_DOMAIN_EVENT_STOPPED:
            transition = virtevent.EVENT_LIFECYCLE_STOPPED
        elif event == libvirt.VIR_DOMAIN_EVENT_STARTED:
            transition = virtevent.EVENT_LIFECYCLE_STARTED
        elif event == libvirt.VIR_DOMAIN_EVENT_SUSPENDED:
            if detail == libvirt.VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY:
                transition = virtevent.EVENT_LIFECYCLE_POSTCOPY_STARTED
            elif detail == libvirt.VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED:
                # VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED is also sent when live
                # migration of the guest fails, so we cannot simply rely
                # on the event itself but need to check if the job itself was
                # successful.
                # NOTE(mriedem): The job check logic here is copied from
                # LibvirtDriver._live_migration_monitor.
                guest = libvirt_guest.Guest(dom)
                info = guest.get_job_info()
                if info.type == libvirt.VIR_DOMAIN_JOB_NONE:
                    # Either still running, or failed or completed,
                    # lets untangle the mess.
                    info.type = libvirt_migrate.find_job_type(guest,
                                                              instance=None,
                                                              logging_ok=False)

                if info.type == libvirt.VIR_DOMAIN_JOB_COMPLETED:
                    transition = virtevent.EVENT_LIFECYCLE_MIGRATION_COMPLETED
                else:
                    # Failed or some other status we don't know about, so just
                    # opt to report the guest is paused.
                    transition = virtevent.EVENT_LIFECYCLE_PAUSED
            else:
                transition = virtevent.EVENT_LIFECYCLE_PAUSED
        elif event == libvirt.VIR_DOMAIN_EVENT_RESUMED:
            transition = virtevent.EVENT_LIFECYCLE_RESUMED

        if transition is not None:
            self._queue_event(virtevent.LifecycleEvent(uuid, transition))
Example #14
0
    def _emit_event(self, pvm_uuid, inst):
        # Get the current state
        try:
            pvm_state = vm.get_vm_qp(self._driver.adapter, pvm_uuid,
                                     'PartitionState')
        except exception.InstanceNotFound:
            LOG.debug("LPAR %s was deleted while event was delayed.",
                      pvm_uuid,
                      instance=inst)
            return

        LOG.debug('New state %s for partition %s',
                  pvm_state,
                  pvm_uuid,
                  instance=inst)

        inst = _get_instance(inst, pvm_uuid)
        if inst is None:
            LOG.debug("Not emitting LifecycleEvent: no instance for LPAR %s",
                      pvm_uuid)
            return

        # If we're in the middle of a nova-driven operation, no event necessary
        if inst.task_state in _NO_EVENT_TASK_STATES:
            LOG.debug("Not emitting LifecycleEvent: instance task_state is %s",
                      inst.task_state,
                      instance=inst)
            return

        # See if it's really a change of state from what OpenStack knows
        transition = vm.translate_event(pvm_state, inst.power_state)
        if transition is None:
            LOG.debug(
                "No LifecycleEvent necessary for pvm_state(%s) and "
                "power_state(%s).",
                pvm_state,
                power_state.STATE_MAP[inst.power_state],
                instance=inst)
            return

        # Log as if normal event
        lce = event.LifecycleEvent(inst.uuid, transition)
        LOG.info('Sending LifecycleEvent for instance state change to: %s',
                 pvm_state,
                 instance=inst)
        self._driver.emit_event(lce)

        # Delete out the queue
        del self._delayed_event_threads[pvm_uuid]
Example #15
0
    def test_event_bad_callback(self):
        # Check that if a callback raises an exception,
        # it does not propagate back out of the
        # 'emit_event' call

        def handler(event):
            raise Exception("Hit Me!")

        self.connection.register_event_listener(handler)

        event1 = virtevent.LifecycleEvent(
            "cef19ce0-0ca2-11df-855d-b19fbce37686",
            virtevent.EVENT_LIFECYCLE_STARTED)

        self.connection.emit_event(event1)
Example #16
0
    def _event_lifecycle_callback(conn, dom, event, detail, opaque):
        """Receives lifecycle events from libvirt.

        NB: this method is executing in a native thread, not
        an eventlet coroutine. It can only invoke other libvirt
        APIs, or use self._queue_event(). Any use of logging APIs
        in particular is forbidden.
        """

        self = opaque

        uuid = dom.UUIDString()
        transition = None
        if event == libvirt.VIR_DOMAIN_EVENT_STOPPED:
            transition = virtevent.EVENT_LIFECYCLE_STOPPED
        elif event == libvirt.VIR_DOMAIN_EVENT_STARTED:
            transition = virtevent.EVENT_LIFECYCLE_STARTED
        elif event == libvirt.VIR_DOMAIN_EVENT_SUSPENDED:
            # NOTE(siva_krishnan): We have to check if
            # VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY and
            # VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED exist since the current
            # minimum version of libvirt (1.3.1) don't have those attributes.
            # This check can be removed once MIN_LIBVIRT_VERSION is bumped to
            # at least 1.3.3.
            if (hasattr(libvirt, 'VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY')
                    and detail == libvirt.VIR_DOMAIN_EVENT_SUSPENDED_POSTCOPY):
                transition = virtevent.EVENT_LIFECYCLE_POSTCOPY_STARTED
            # FIXME(mriedem): VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED is also sent
            # when live migration of the guest fails, so we cannot simply rely
            # on the event itself but need to check if the job itself was
            # successful.
            # elif (hasattr(libvirt, 'VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED') and
            #         detail == libvirt.VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED):
            #     transition = virtevent.EVENT_LIFECYCLE_MIGRATION_COMPLETED
            else:
                transition = virtevent.EVENT_LIFECYCLE_PAUSED
        elif event == libvirt.VIR_DOMAIN_EVENT_RESUMED:
            transition = virtevent.EVENT_LIFECYCLE_RESUMED

        if transition is not None:
            self._queue_event(virtevent.LifecycleEvent(uuid, transition))
Example #17
0
 def _get_virt_event(self, instance_uuid, instance_state):
     transition = self._TRANSITION_MAP[instance_state]
     return virtevent.LifecycleEvent(uuid=instance_uuid,
                                     transition=transition)