|
91 | 91 | import org.libvirt.SchedUlongParameter; |
92 | 92 | import org.libvirt.Secret; |
93 | 93 | import org.libvirt.VcpuInfo; |
| 94 | +import org.libvirt.event.DomainEvent; |
94 | 95 | import org.libvirt.event.DomainEventDetail; |
95 | 96 | import org.libvirt.event.StoppedDetail; |
96 | 97 | import org.w3c.dom.Document; |
@@ -3608,55 +3609,58 @@ private StartupStorageCommand createLocalStoragePool(String localStoragePath, St |
3608 | 3609 | } |
3609 | 3610 |
|
3610 | 3611 | private void setupLibvirtEventListener() { |
| 3612 | + final Thread libvirtListenerThread = new Thread(() -> { |
| 3613 | + try { |
| 3614 | + Library.runEventLoop(); |
| 3615 | + } catch (LibvirtException e) { |
| 3616 | + s_logger.error("LibvirtException was thrown in event loop: ", e); |
| 3617 | + } catch (InterruptedException e) { |
| 3618 | + s_logger.error("Libvirt event loop was interrupted: ", e); |
| 3619 | + } |
| 3620 | + }); |
| 3621 | + |
3611 | 3622 | try { |
3612 | | - final Thread t = new Thread(() -> { |
3613 | | - try { |
3614 | | - Library.runEventLoop(); |
3615 | | - } catch (LibvirtException e) { |
3616 | | - s_logger.error("LibvirtException was thrown in event loop: ", e); |
3617 | | - } catch (InterruptedException e) { |
3618 | | - s_logger.error("Libvirt event loop was interrupted: ", e); |
3619 | | - } |
3620 | | - }); |
3621 | | - t.setDaemon(true); |
3622 | | - t.start(); |
| 3623 | + libvirtListenerThread.setDaemon(true); |
| 3624 | + libvirtListenerThread.start(); |
3623 | 3625 |
|
3624 | 3626 | Connect conn = LibvirtConnection.getConnection(); |
3625 | | - conn.addLifecycleListener((domain, domainEvent) -> { |
3626 | | - try { |
3627 | | - s_logger.debug(String.format("Got event lifecycle change on Domain %s, event %s", domain.getName(), domainEvent)); |
3628 | | - if (domainEvent != null) { |
3629 | | - switch (domainEvent.getType()) { |
3630 | | - case STOPPED: |
3631 | | - /* libvirt-destroyed VMs have detail StoppedDetail.DESTROYED, self shutdown guests are StoppedDetail.SHUTDOWN |
3632 | | - * Checking for this helps us differentiate between events where cloudstack or admin stopped the VM vs guest |
3633 | | - * initiated, and avoid pushing extra updates for actions we are initiating without a need for extra tracking */ |
3634 | | - DomainEventDetail detail = domainEvent.getDetail(); |
3635 | | - if (StoppedDetail.SHUTDOWN.equals(detail) || StoppedDetail.CRASHED.equals(detail)) { |
3636 | | - s_logger.info("Triggering out of band status update due to completed self-shutdown or crash of VM"); |
3637 | | - _agentStatusUpdater.triggerUpdate(); |
3638 | | - } else { |
3639 | | - s_logger.debug("Event detail: " + detail); |
3640 | | - } |
3641 | | - break; |
3642 | | - default: |
3643 | | - s_logger.debug(String.format("No handling for event %s", domainEvent)); |
3644 | | - } |
3645 | | - } |
3646 | | - } catch (LibvirtException e) { |
3647 | | - s_logger.error("Libvirt exception while processing lifecycle event", e); |
3648 | | - } catch (Throwable e) { |
3649 | | - s_logger.error("Error during lifecycle", e); |
3650 | | - } |
3651 | | - return 0; |
3652 | | - }); |
| 3627 | + conn.addLifecycleListener(this::onDomainLifecycleChange); |
3653 | 3628 |
|
3654 | 3629 | s_logger.debug("Set up the libvirt domain event lifecycle listener"); |
3655 | 3630 | } catch (LibvirtException e) { |
3656 | 3631 | s_logger.error("Failed to get libvirt connection for domain event lifecycle", e); |
3657 | 3632 | } |
3658 | 3633 | } |
3659 | 3634 |
|
| 3635 | + private int onDomainLifecycleChange(Domain domain, DomainEvent domainEvent) { |
| 3636 | + try { |
| 3637 | + s_logger.debug(String.format("Got event lifecycle change on Domain %s, event %s", domain.getName(), domainEvent)); |
| 3638 | + if (domainEvent != null) { |
| 3639 | + switch (domainEvent.getType()) { |
| 3640 | + case STOPPED: |
| 3641 | + /* libvirt-destroyed VMs have detail StoppedDetail.DESTROYED, self shutdown guests are StoppedDetail.SHUTDOWN |
| 3642 | + * Checking for this helps us differentiate between events where cloudstack or admin stopped the VM vs guest |
| 3643 | + * initiated, and avoid pushing extra updates for actions we are initiating without a need for extra tracking */ |
| 3644 | + DomainEventDetail detail = domainEvent.getDetail(); |
| 3645 | + if (StoppedDetail.SHUTDOWN.equals(detail) || StoppedDetail.CRASHED.equals(detail)) { |
| 3646 | + s_logger.info("Triggering out of band status update due to completed self-shutdown or crash of VM"); |
| 3647 | + _agentStatusUpdater.triggerUpdate(); |
| 3648 | + } else { |
| 3649 | + s_logger.debug("Event detail: " + detail); |
| 3650 | + } |
| 3651 | + break; |
| 3652 | + default: |
| 3653 | + s_logger.debug(String.format("No handling for event %s", domainEvent)); |
| 3654 | + } |
| 3655 | + } |
| 3656 | + } catch (LibvirtException e) { |
| 3657 | + s_logger.error("Libvirt exception while processing lifecycle event", e); |
| 3658 | + } catch (Throwable e) { |
| 3659 | + s_logger.error("Error during lifecycle", e); |
| 3660 | + } |
| 3661 | + return 0; |
| 3662 | + } |
| 3663 | + |
3660 | 3664 | public String diskUuidToSerial(String uuid) { |
3661 | 3665 | String uuidWithoutHyphen = uuid.replace("-",""); |
3662 | 3666 | return uuidWithoutHyphen.substring(0, Math.min(uuidWithoutHyphen.length(), 20)); |
|
0 commit comments