|
93 | 93 | import org.libvirt.SchedUlongParameter; |
94 | 94 | import org.libvirt.Secret; |
95 | 95 | import org.libvirt.VcpuInfo; |
96 | | -import org.libvirt.event.DomainEvent; |
97 | | -import org.libvirt.event.DomainEventDetail; |
98 | | -import org.libvirt.event.StoppedDetail; |
99 | 96 | import org.w3c.dom.Document; |
100 | 97 | import org.w3c.dom.Element; |
101 | 98 | import org.w3c.dom.Node; |
@@ -469,7 +466,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv |
469 | 466 | protected CPUStat cpuStat = new CPUStat(); |
470 | 467 | protected MemStat memStat = new MemStat(dom0MinMem, dom0OvercommitMem); |
471 | 468 | private final LibvirtUtilitiesHelper libvirtUtilitiesHelper = new LibvirtUtilitiesHelper(); |
472 | | - private AgentStatusUpdater _agentStatusUpdater; |
| 469 | + private LibvirtDomainListener libvirtDomainListener; |
473 | 470 |
|
474 | 471 | protected Boolean enableManuallySettingCpuTopologyOnKvmVm = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.ENABLE_MANUALLY_SETTING_CPU_TOPOLOGY_ON_KVM_VM); |
475 | 472 |
|
@@ -503,8 +500,23 @@ protected long getHypervisorQemuVersion() { |
503 | 500 | } |
504 | 501 |
|
505 | 502 | @Override |
506 | | - public void registerStatusUpdater(AgentStatusUpdater updater) { |
507 | | - _agentStatusUpdater = updater; |
| 503 | + public synchronized void registerStatusUpdater(AgentStatusUpdater updater) { |
| 504 | + if (AgentPropertiesFileHandler.getPropertyValue(AgentProperties.LIBVIRT_EVENTS_ENABLED)) { |
| 505 | + try { |
| 506 | + Connect conn = LibvirtConnection.getConnection(); |
| 507 | + if (libvirtDomainListener != null) { |
| 508 | + LOGGER.debug("Clearing old domain listener"); |
| 509 | + conn.removeLifecycleListener(libvirtDomainListener); |
| 510 | + } |
| 511 | + libvirtDomainListener = new LibvirtDomainListener(updater); |
| 512 | + conn.addLifecycleListener(libvirtDomainListener); |
| 513 | + LOGGER.debug("Set up the libvirt domain event lifecycle listener"); |
| 514 | + } catch (LibvirtException e) { |
| 515 | + LOGGER.error("Failed to get libvirt connection for domain event lifecycle", e); |
| 516 | + } |
| 517 | + } else { |
| 518 | + LOGGER.debug("Libvirt event listening is disabled, not registering status updater"); |
| 519 | + } |
508 | 520 | } |
509 | 521 |
|
510 | 522 | @Override |
@@ -1879,6 +1891,10 @@ public String startVM(final Connect conn, final String vmName, final String doma |
1879 | 1891 | public boolean stop() { |
1880 | 1892 | try { |
1881 | 1893 | final Connect conn = LibvirtConnection.getConnection(); |
| 1894 | + if (AgentPropertiesFileHandler.getPropertyValue(AgentProperties.LIBVIRT_EVENTS_ENABLED) && libvirtDomainListener != null) { |
| 1895 | + LOGGER.debug("Clearing old domain listener"); |
| 1896 | + conn.removeLifecycleListener(libvirtDomainListener); |
| 1897 | + } |
1882 | 1898 | conn.close(); |
1883 | 1899 | } catch (final LibvirtException e) { |
1884 | 1900 | LOGGER.trace("Ignoring libvirt error.", e); |
@@ -3699,50 +3715,9 @@ private StartupStorageCommand createLocalStoragePool(String localStoragePath, St |
3699 | 3715 | } catch (final CloudRuntimeException e) { |
3700 | 3716 | LOGGER.debug("Unable to initialize local storage pool: " + e); |
3701 | 3717 | } |
3702 | | - setupLibvirtEventListener(); |
3703 | 3718 | return sscmd; |
3704 | 3719 | } |
3705 | 3720 |
|
3706 | | - private void setupLibvirtEventListener() { |
3707 | | - try { |
3708 | | - Connect conn = LibvirtConnection.getConnection(); |
3709 | | - conn.addLifecycleListener(this::onDomainLifecycleChange); |
3710 | | - |
3711 | | - logger.debug("Set up the libvirt domain event lifecycle listener"); |
3712 | | - } catch (LibvirtException e) { |
3713 | | - logger.error("Failed to get libvirt connection for domain event lifecycle", e); |
3714 | | - } |
3715 | | - } |
3716 | | - |
3717 | | - private int onDomainLifecycleChange(Domain domain, DomainEvent domainEvent) { |
3718 | | - try { |
3719 | | - logger.debug(String.format("Got event lifecycle change on Domain %s, event %s", domain.getName(), domainEvent)); |
3720 | | - if (domainEvent != null) { |
3721 | | - switch (domainEvent.getType()) { |
3722 | | - case STOPPED: |
3723 | | - /* libvirt-destroyed VMs have detail StoppedDetail.DESTROYED, self shutdown guests are StoppedDetail.SHUTDOWN |
3724 | | - * Checking for this helps us differentiate between events where cloudstack or admin stopped the VM vs guest |
3725 | | - * initiated, and avoid pushing extra updates for actions we are initiating without a need for extra tracking */ |
3726 | | - DomainEventDetail detail = domainEvent.getDetail(); |
3727 | | - if (StoppedDetail.SHUTDOWN.equals(detail) || StoppedDetail.CRASHED.equals(detail) || StoppedDetail.FAILED.equals(detail)) { |
3728 | | - logger.info("Triggering out of band status update due to completed self-shutdown or crash of VM"); |
3729 | | - _agentStatusUpdater.triggerUpdate(); |
3730 | | - } else { |
3731 | | - logger.debug("Event detail: " + detail); |
3732 | | - } |
3733 | | - break; |
3734 | | - default: |
3735 | | - logger.debug(String.format("No handling for event %s", domainEvent)); |
3736 | | - } |
3737 | | - } |
3738 | | - } catch (LibvirtException e) { |
3739 | | - logger.error("Libvirt exception while processing lifecycle event", e); |
3740 | | - } catch (Throwable e) { |
3741 | | - logger.error("Error during lifecycle", e); |
3742 | | - } |
3743 | | - return 0; |
3744 | | - } |
3745 | | - |
3746 | 3721 | public String diskUuidToSerial(String uuid) { |
3747 | 3722 | String uuidWithoutHyphen = uuid.replace("-",""); |
3748 | 3723 | return uuidWithoutHyphen.substring(0, Math.min(uuidWithoutHyphen.length(), 20)); |
|
0 commit comments