package org.zstack.compute.host; import org.springframework.beans.factory.annotation.Autowired; import org.zstack.core.componentloader.PluginRegistry; import org.zstack.header.Component; import org.zstack.header.core.Completion; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.host.*; import org.zstack.utils.CollectionUtils; import org.zstack.utils.Utils; import org.zstack.utils.function.ForEachFunction; import org.zstack.utils.logging.CLogger; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class HostExtensionPointEmitter implements Component { private static final CLogger logger = Utils.getLogger(HostExtensionPointEmitter.class); @Autowired private PluginRegistry pluginRgty; private List<HostPingTaskExtensionPoint> pingTaskExts = new ArrayList<>(); private List<HostDeleteExtensionPoint> deleteHostExts = new ArrayList<>(); private List<HostChangeStateExtensionPoint> changeStateExts = new ArrayList<>(); private List<HostConnectionReestablishExtensionPoint> connetionReestablishExts = new ArrayList<>(); private List<HostAddExtensionPoint> addHostExts = new ArrayList<>(); public void preDelete(HostInventory hinv) throws HostException { for (HostDeleteExtensionPoint extp : deleteHostExts) { try { extp.preDeleteHost(hinv); } catch (HostException he) { logger.debug(String.format("extension[%s] refuses to delete host[uuid:%s] because %s", extp.getClass().getName(), hinv.getUuid(), he.getMessage()), he); throw he; } catch (Exception e) { logger.warn(String.format("Unhandled exception happened while calling %s", extp.getClass().getName()), e); } } } public void preChange(HostVO vo, HostStateEvent event) throws HostException { HostState next = vo.getState().nextState(event); HostInventory hinv = HostInventory.valueOf(vo); for (HostChangeStateExtensionPoint extp : changeStateExts) { try { extp.preChangeHostState(hinv, event, next); } catch (HostException he) { logger.debug(String.format("%s refuse to change host state by[HostStateEvent:%s] because %s", extp.getClass() .getCanonicalName(), event, he.getMessage()), he); throw he; } catch (Exception e) { logger.warn(String.format("Unhandled exception happened while calling %s", extp.getClass().getName()), e); } } } public void preChange(List<HostVO> vos, HostStateEvent event) throws HostException { for (HostVO vo : vos) { preChange(vo, event); } } public void beforeChange(HostVO vo, final HostStateEvent event) { final HostInventory hinv = HostInventory.valueOf(vo); final HostState next = vo.getState().nextState(event); CollectionUtils.safeForEach(changeStateExts, new ForEachFunction<HostChangeStateExtensionPoint>() { @Override public void run(HostChangeStateExtensionPoint extp) { extp.beforeChangeHostState(hinv, event, next); } }); } public void afterChange(HostVO vo, final HostStateEvent event, final HostState prevState) { final HostInventory hinv = HostInventory.valueOf(vo); CollectionUtils.safeForEach(changeStateExts, new ForEachFunction<HostChangeStateExtensionPoint>() { @Override public void run(HostChangeStateExtensionPoint extp) { extp.afterChangeHostState(hinv, event, prevState); } }); } public void beforeDelete(final HostInventory hinv) { CollectionUtils.safeForEach(deleteHostExts, new ForEachFunction<HostDeleteExtensionPoint>() { @Override public void run(HostDeleteExtensionPoint extp) { extp.beforeDeleteHost(hinv); } }); } public void afterDelete(final HostInventory hinv) { CollectionUtils.safeForEach(deleteHostExts, new ForEachFunction<HostDeleteExtensionPoint>() { @Override public void run(HostDeleteExtensionPoint extp) { extp.afterDeleteHost(hinv); } }); } public void hostPingTask(final HypervisorType type, final HostInventory inv) { CollectionUtils.safeForEach(pingTaskExts, new ForEachFunction<HostPingTaskExtensionPoint>() { @Override public void run(HostPingTaskExtensionPoint ext) { if (ext.getHypervisorType().equals(type)) { ext.executeTaskAlongWithPingTask(inv); } } }); } public void connectionReestablished(HypervisorType hvType, HostInventory host) throws HostException { for (HostConnectionReestablishExtensionPoint ext : connetionReestablishExts) { if (ext.getHypervisorTypeForReestablishExtensionPoint().equals(hvType)) { try { ext.connectionReestablished(host); } catch (HostException he) { throw he; } catch (Exception e) { logger.warn(String.format("Unhandled exception happened while calling %s", ext.getClass().getName()), e); } } } } private void beforeAddHost(final Iterator<HostAddExtensionPoint> it, final HostInventory host, final Completion completion) { if (!it.hasNext()) { completion.success(); return; } HostAddExtensionPoint ext = it.next(); ext.beforeAddHost(host, new Completion(completion) { @Override public void success() { beforeAddHost(it, host, completion); } @Override public void fail(ErrorCode errorCode) { completion.fail(errorCode); } }); } public void beforeAddHost(HostInventory host, Completion completion) { if (addHostExts.isEmpty()) { completion.success(); return; } beforeAddHost(addHostExts.iterator(), host, completion); } public void afterAddHost(HostInventory host, Completion completion) { if (addHostExts.isEmpty()) { completion.success(); return; } afterAddHost(addHostExts.iterator(), host, completion); } private void afterAddHost(final Iterator<HostAddExtensionPoint> it, final HostInventory host, final Completion completion) { if (!it.hasNext()) { completion.success(); return; } HostAddExtensionPoint ext = it.next(); ext.afterAddHost(host, new Completion(completion) { @Override public void success() { afterAddHost(it, host, completion); } @Override public void fail(ErrorCode errorCode) { completion.fail(errorCode); } }); } private void populateExtensions() { pingTaskExts = pluginRgty.getExtensionList(HostPingTaskExtensionPoint.class); deleteHostExts = pluginRgty.getExtensionList(HostDeleteExtensionPoint.class); changeStateExts = pluginRgty.getExtensionList(HostChangeStateExtensionPoint.class); connetionReestablishExts = pluginRgty.getExtensionList(HostConnectionReestablishExtensionPoint.class); addHostExts = pluginRgty.getExtensionList(HostAddExtensionPoint.class); } @Override public boolean start() { populateExtensions(); return true; } @Override public boolean stop() { return true; } }