/* * Copyright 2014 by SCSK Corporation. * * This file is part of PrimeCloud Controller(TM). * * PrimeCloud Controller(TM) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * PrimeCloud Controller(TM) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PrimeCloud Controller(TM). If not, see <http://www.gnu.org/licenses/>. */ package jp.primecloud.auto.process; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import jp.primecloud.auto.common.log.LoggingUtils; import jp.primecloud.auto.common.status.ComponentInstanceStatus; import jp.primecloud.auto.common.status.InstanceCoodinateStatus; import jp.primecloud.auto.common.status.InstanceStatus; import jp.primecloud.auto.common.status.LoadBalancerInstanceStatus; import jp.primecloud.auto.common.status.LoadBalancerListenerStatus; import jp.primecloud.auto.common.status.LoadBalancerStatus; import jp.primecloud.auto.entity.crud.ComponentInstance; import jp.primecloud.auto.entity.crud.Farm; import jp.primecloud.auto.entity.crud.Instance; import jp.primecloud.auto.entity.crud.LoadBalancer; import jp.primecloud.auto.entity.crud.LoadBalancerInstance; import jp.primecloud.auto.entity.crud.LoadBalancerListener; import jp.primecloud.auto.entity.crud.User; import jp.primecloud.auto.exception.MultiCauseException; import jp.primecloud.auto.log.EventLogger; import jp.primecloud.auto.process.lb.LoadBalancerProcess; import jp.primecloud.auto.service.ServiceSupport; import org.apache.commons.lang.BooleanUtils; /** * <p> * TODO: クラスコメントを記述 * </p> * */ public class ProcessManager extends ServiceSupport { protected InstanceProcess instanceProcess; protected ComponentProcess componentProcess; protected InstancesProcess instancesProcess; protected LoadBalancerProcess loadBalancerProcess; protected ExecutorService executorService; protected EventLogger eventLogger; public void process() { // 処理対象のファームを取得 List<Farm> farms = new ArrayList<Farm>(); List<Farm> allFarms = farmDao.readAll(); for (Farm farm : allFarms) { if (BooleanUtils.isTrue(farm.getScheduled())) { farms.add(farm); } } List<Long> farmNos = new ArrayList<Long>(); for (Farm farm : farms) { farmNos.add(farm.getFarmNo()); } log.debug("farmNos: " + farmNos); if (farms.isEmpty()) { return; } for (Farm farm : farms) { // TODO: ファーム処理の実行停止状態の場合はスキップ processFarm(farm); } } protected void processFarm(Farm farm) { // インスタンス、ロードバランサの開始処理 boolean next = processStartInstance(farm); boolean next2 = processStartLoadBalancer(farm); if (!next || !next2) { return; } // インスタンス群の協調開始処理 next = processStartInstances(farm); if (!next) { return; } // コンポーネントの設定処理 next = processConfigureComponent(farm); if (!next) { return; } // インスタンス群の協調停止処理 next = processStopInstances(farm); if (!next) { return; } // インスタンス、ロードバランサの停止処理 next = processStopInstance(farm); next2 = processStopLoadBalancer(farm); if (!next || !next2) { return; } // ファームを処理対象外にする unscheduled(farm.getFarmNo()); } protected void unscheduled(Long farmNo) { Farm farm = farmDao.read(farmNo); if (BooleanUtils.isTrue(farm.getScheduled())) { farm.setScheduled(false); farmDao.update(farm); } } protected boolean processStartInstance(final Farm farm) { // 有効なインスタンスを取得 List<Instance> instances = new ArrayList<Instance>(); List<Instance> allInstances = instanceDao.readByFarmNo(farm.getFarmNo()); for (Instance instance : allInstances) { // ロードバランサインスタンスは対象外 if (BooleanUtils.isTrue(instance.getLoadBalancer())) { continue; } if (BooleanUtils.isTrue(instance.getEnabled())) { instances.add(instance); } } // 有効なインスタンスが無い場合 if (instances.isEmpty()) { return true; } // インスタンスの状態を取得 boolean processing = false; List<Long> targetInstanceNos = new ArrayList<Long>(); for (Instance instance : instances) { InstanceStatus status = InstanceStatus.fromStatus(instance.getStatus()); if (status != InstanceStatus.RUNNING && status != InstanceStatus.WARNING) { processing = true; if (status == InstanceStatus.STOPPED) { targetInstanceNos.add(instance.getInstanceNo()); } } } // 停止しているインスタンスを起動する if (!targetInstanceNos.isEmpty()) { final User user = userDao.read(farm.getUserNo()); for (final Long instanceNo : targetInstanceNos) { Runnable runnable = new Runnable() { @Override public void run() { LoggingUtils.setUserNo(user.getUserNo()); LoggingUtils.setUserName(user.getUsername()); LoggingUtils.setFarmNo(farm.getFarmNo()); LoggingUtils.setFarmName(farm.getFarmName()); try { instanceProcess.start(instanceNo); } catch (MultiCauseException ignore) { } catch (Throwable e) { log.error(e.getMessage(), e); // イベントログ出力 eventLogger.error("SystemError", new Object[] { e.getMessage() }); } finally { LoggingUtils.removeContext(); } } }; executorService.execute(runnable); } } // 処理中のインスタンスがある場合 if (processing) { return false; } return true; } protected boolean processStartInstances(final Farm farm) { // コンポーネントが処理中の場合 if (BooleanUtils.isTrue(farm.getComponentProcessing())) { return false; } // 起動しているインスタンスの中で、有効だが協調していないものがあるかどうかチェック boolean coodinated = true; List<Instance> allInstances = instanceDao.readByFarmNo(farm.getFarmNo()); for (Instance instance : allInstances) { if (InstanceStatus.fromStatus(instance.getStatus()) == InstanceStatus.RUNNING) { if (BooleanUtils.isTrue(instance.getEnabled())) { if (InstanceCoodinateStatus.fromStatus(instance.getCoodinateStatus()) == InstanceCoodinateStatus.UN_COODINATED) { if (puppetInstanceDao.countByInstanceNo(instance.getInstanceNo()) > 0) { coodinated = false; break; } } } } } // 協調すべきインスタンスがある場合、インスタンス群の協調設定処理を実行 if (!coodinated) { final User user = userDao.read(farm.getUserNo()); Runnable runnable = new Runnable() { @Override public void run() { LoggingUtils.setUserNo(user.getUserNo()); LoggingUtils.setUserName(user.getUsername()); LoggingUtils.setFarmNo(farm.getFarmNo()); LoggingUtils.setFarmName(farm.getFarmName()); try { instancesProcess.start(farm.getFarmNo()); } catch (MultiCauseException ignore) { } catch (Throwable e) { log.error(e.getMessage(), e); // イベントログ出力 eventLogger.error("SystemError", new Object[] { e.getMessage() }); } finally { LoggingUtils.removeContext(); } } }; executorService.execute(runnable); } return coodinated; } protected boolean processConfigureComponent(final Farm farm) { // コンポーネントが処理中の場合 if (BooleanUtils.isTrue(farm.getComponentProcessing())) { return false; } boolean configured = true; // 起動中のInstanceのComponentInstnaceを全て取得 List<Instance> instances = instanceDao.readByFarmNo(farm.getFarmNo()); List<Long> instanceNos = new ArrayList<Long>(); for (Instance instance : instances) { // ロードバランサインスタンスは対象外 if (BooleanUtils.isTrue(instance.getLoadBalancer())) { continue; } if (InstanceStatus.fromStatus(instance.getStatus()) == InstanceStatus.RUNNING) { instanceNos.add(instance.getInstanceNo()); } } List<ComponentInstance> componentInstances = componentInstanceDao.readInInstanceNos(instanceNos); // ComponentInstanceが設定済みかどうかのチェック for (ComponentInstance componentInstance : componentInstances) { ComponentInstanceStatus status = ComponentInstanceStatus.fromStatus(componentInstance.getStatus()); if (BooleanUtils.isTrue(componentInstance.getEnabled())) { if (status == ComponentInstanceStatus.WARNING) { // 起動対象のコンポーネントが異常状態の場合、設定処理をスキップする unscheduled(farm.getFarmNo()); return false; } else if (status != ComponentInstanceStatus.RUNNING) { configured = false; } } else { if (status != ComponentInstanceStatus.STOPPED) { configured = false; } } } // ロードバランサ情報の取得 List<LoadBalancer> loadBalancers = null; List<LoadBalancerListener> listeners = null; List<LoadBalancerInstance> lbInstances = null; Map<Long, LoadBalancer> loadBalancerMap = null; Map<Long, Instance> instanceMap = null; if (configured) { loadBalancers = loadBalancerDao.readByFarmNo(farm.getFarmNo()); loadBalancerMap = new HashMap<Long, LoadBalancer>(); for (LoadBalancer loadBalancer : loadBalancers) { loadBalancerMap.put(loadBalancer.getLoadBalancerNo(), loadBalancer); } listeners = loadBalancerListenerDao.readInLoadBalancerNos(loadBalancerMap.keySet()); lbInstances = loadBalancerInstanceDao.readInLoadBalancerNos(loadBalancerMap.keySet()); instanceMap = new HashMap<Long, Instance>(); for (Instance instance : instances) { instanceMap.put(instance.getInstanceNo(), instance); } } // ロードバランサリスナーが設定済みかどうかチェック if (configured) { for (LoadBalancerListener listener : listeners) { LoadBalancer loadBalancer = loadBalancerMap.get(listener.getLoadBalancerNo()); LoadBalancerStatus status = LoadBalancerStatus.fromStatus(loadBalancer.getStatus()); LoadBalancerListenerStatus status2 = LoadBalancerListenerStatus.fromStatus(listener.getStatus()); if (BooleanUtils.isTrue(loadBalancer.getEnabled())) { if (status == LoadBalancerStatus.RUNNING) { // ロードバランサが有効で起動状態の場合 if (BooleanUtils.isTrue(listener.getEnabled())) { if (status2 == LoadBalancerListenerStatus.WARNING) { // 起動対象のリスナーが異常状態の場合、設定処理をスキップする unscheduled(farm.getFarmNo()); return false; } else if (status2 != LoadBalancerListenerStatus.RUNNING) { configured = false; } } else { if (status2 != LoadBalancerListenerStatus.STOPPED) { configured = false; } } } } else { if (status == LoadBalancerStatus.RUNNING || status == LoadBalancerStatus.WARNING) { // ロードバランサが無効で起動または異常状態の場合 if (status2 != LoadBalancerListenerStatus.STOPPED) { configured = false; } } } } } // ロードバランサインスタンスが設定済みかどうかチェック if (configured) { for (LoadBalancerInstance lbInstance : lbInstances) { LoadBalancer loadBalancer = loadBalancerMap.get(lbInstance.getLoadBalancerNo()); LoadBalancerStatus status = LoadBalancerStatus.fromStatus(loadBalancer.getStatus()); LoadBalancerInstanceStatus status2 = LoadBalancerInstanceStatus.fromStatus(lbInstance.getStatus()); Instance instance = instanceMap.get(lbInstance.getInstanceNo()); InstanceStatus instanceStatus = InstanceStatus.fromStatus(instance.getStatus()); // インスタンスが起動状態のもののみチェックする if (instanceStatus == InstanceStatus.RUNNING) { if (BooleanUtils.isTrue(loadBalancer.getEnabled()) && BooleanUtils.isTrue(instance.getEnabled())) { if (status == LoadBalancerStatus.RUNNING) { // ロードバランサとインスタンスが有効で、ロードバランサが起動状態の場合 if (BooleanUtils.isTrue(lbInstance.getEnabled())) { if (status2 == LoadBalancerInstanceStatus.WARNING) { // 起動対象のロードバランサインスタンスが異常状態の場合、設定処理をスキップする unscheduled(farm.getFarmNo()); return false; } else if (status2 != LoadBalancerInstanceStatus.RUNNING) { configured = false; } } else { if (status2 != LoadBalancerInstanceStatus.STOPPED) { configured = false; } } } } else { if (status == LoadBalancerStatus.RUNNING || status == LoadBalancerStatus.WARNING) { // ロードバランサまたはインスタンスが無効で、ロードバランサが起動または異常状態の場合 if (status2 != LoadBalancerInstanceStatus.STOPPED) { configured = false; } } } } } } // 強制設定を行うコンポーネントがある場合、未設定状態にする if (configured) { for (ComponentInstance componentInstance : componentInstances) { if (BooleanUtils.isTrue(componentInstance.getConfigure())) { configured = false; break; } } } // 設定を行うロードバランサがある場合、未設定状態にする if (configured) { for (LoadBalancer loadBalancer : loadBalancers) { if (BooleanUtils.isTrue(loadBalancer.getConfigure())) { LoadBalancerStatus status = LoadBalancerStatus.fromStatus(loadBalancer.getStatus()); if (BooleanUtils.isTrue(loadBalancer.getEnabled())) { if (status == LoadBalancerStatus.RUNNING) { configured = false; break; } } else { if (status == LoadBalancerStatus.RUNNING || status == LoadBalancerStatus.WARNING) { configured = false; break; } } } } } // 設定を行うロードバランサリスナーがある場合、未設定状態にする if (configured) { for (LoadBalancerListener listener : listeners) { if (BooleanUtils.isTrue(listener.getConfigure())) { LoadBalancer loadBalancer = loadBalancerMap.get(listener.getLoadBalancerNo()); LoadBalancerStatus status = LoadBalancerStatus.fromStatus(loadBalancer.getStatus()); if (BooleanUtils.isTrue(loadBalancer.getEnabled())) { if (status == LoadBalancerStatus.RUNNING) { configured = false; break; } } else { if (status == LoadBalancerStatus.RUNNING || status == LoadBalancerStatus.WARNING) { configured = false; break; } } } } } // 設定済みでない場合、コンポーネントの設定処理を実行 if (!configured) { final User user = userDao.read(farm.getUserNo()); Runnable runnable = new Runnable() { @Override public void run() { LoggingUtils.setUserNo(user.getUserNo()); LoggingUtils.setUserName(user.getUsername()); LoggingUtils.setFarmNo(farm.getFarmNo()); LoggingUtils.setFarmName(farm.getFarmName()); try { componentProcess.configure(farm.getFarmNo()); } catch (MultiCauseException ignore) { } catch (Throwable e) { log.error(e.getMessage(), e); // イベントログ出力 eventLogger.error("SystemError", new Object[] { e.getMessage() }); } finally { LoggingUtils.removeContext(); } } }; executorService.execute(runnable); } return configured; } protected boolean processStopInstances(final Farm farm) { // コンポーネントが処理中の場合 if (BooleanUtils.isTrue(farm.getComponentProcessing())) { return false; } // 起動しているインスタンスの中で、無効だが協調しているものがあるかどうかチェック boolean coodinated = false; List<Instance> allInstances = instanceDao.readByFarmNo(farm.getFarmNo()); for (Instance instance : allInstances) { if (InstanceStatus.fromStatus(instance.getStatus()) == InstanceStatus.RUNNING) { if (BooleanUtils.isNotTrue(instance.getEnabled())) { if (InstanceCoodinateStatus.fromStatus(instance.getCoodinateStatus()) == InstanceCoodinateStatus.COODINATED) { if (puppetInstanceDao.countByInstanceNo(instance.getInstanceNo()) > 0) { coodinated = true; break; } } } } } // 協調すべきでないインスタンスがある場合、インスタンス群の協調設定処理を実行 if (coodinated) { final User user = userDao.read(farm.getUserNo()); Runnable runnable = new Runnable() { @Override public void run() { LoggingUtils.setUserNo(user.getUserNo()); LoggingUtils.setUserName(user.getUsername()); LoggingUtils.setFarmNo(farm.getFarmNo()); LoggingUtils.setFarmName(farm.getFarmName()); try { instancesProcess.stop(farm.getFarmNo()); } catch (MultiCauseException ignore) { } catch (Throwable e) { log.error(e.getMessage(), e); // イベントログ出力 eventLogger.error("SystemError", new Object[] { e.getMessage() }); } finally { LoggingUtils.removeContext(); } } }; executorService.execute(runnable); } return !coodinated; } protected boolean processStopInstance(final Farm farm) { // 無効なインスタンスを取得 List<Instance> instances = new ArrayList<Instance>(); List<Instance> allInstances = instanceDao.readByFarmNo(farm.getFarmNo()); for (Instance instance : allInstances) { // ロードバランサインスタンスは対象外 if (BooleanUtils.isTrue(instance.getLoadBalancer())) { continue; } if (BooleanUtils.isNotTrue(instance.getEnabled())) { instances.add(instance); } } // 無効なインスタンスが無い場合 if (instances.isEmpty()) { return true; } // インスタンスの状態を取得 boolean processing = false; List<Long> targetInstanceNos = new ArrayList<Long>(); for (Instance instance : instances) { InstanceStatus status = InstanceStatus.fromStatus(instance.getStatus()); if (status != InstanceStatus.STOPPED) { processing = true; if (status == InstanceStatus.RUNNING || status == InstanceStatus.WARNING) { targetInstanceNos.add(instance.getInstanceNo()); } } } // 起動しているインスタンスを停止する if (!targetInstanceNos.isEmpty()) { final User user = userDao.read(farm.getUserNo()); for (final Long instanceNo : targetInstanceNos) { Runnable runnable = new Runnable() { @Override public void run() { LoggingUtils.setUserNo(user.getUserNo()); LoggingUtils.setUserName(user.getUsername()); LoggingUtils.setFarmNo(farm.getFarmNo()); LoggingUtils.setFarmName(farm.getFarmName()); try { log.debug("instanceProcess.stop(instanceNo):" + String.valueOf(instanceNo)); instanceProcess.stop(instanceNo); } catch (MultiCauseException ignore) { } catch (Throwable e) { log.error(e.getMessage(), e); // イベントログ出力 eventLogger.error("SystemError", new Object[] { e.getMessage() }); } finally { LoggingUtils.removeContext(); } } }; executorService.execute(runnable); } } // 処理中のインスタンスがある場合 if (processing) { return false; } return true; } protected boolean processStartLoadBalancer(final Farm farm) { // 有効なロードバランサを取得 List<LoadBalancer> loadBalancers = new ArrayList<LoadBalancer>(); List<LoadBalancer> allLoadBalancers = loadBalancerDao.readByFarmNo(farm.getFarmNo()); for (LoadBalancer loadBalancer : allLoadBalancers) { if (BooleanUtils.isTrue(loadBalancer.getEnabled())) { loadBalancers.add(loadBalancer); } } // 有効なロードバランサがない場合 if (loadBalancers.isEmpty()) { return true; } // ロードバランサの状態を取得 boolean processing = false; List<Long> targetLoadBalancerNos = new ArrayList<Long>(); for (LoadBalancer loadBalancer : loadBalancers) { LoadBalancerStatus status = LoadBalancerStatus.fromStatus(loadBalancer.getStatus()); if (status != LoadBalancerStatus.RUNNING && status != LoadBalancerStatus.WARNING) { processing = true; if (status == LoadBalancerStatus.STOPPED) { targetLoadBalancerNos.add(loadBalancer.getLoadBalancerNo()); } } } // 停止しているロードバランサを起動する if (!targetLoadBalancerNos.isEmpty()) { final User user = userDao.read(farm.getUserNo()); for (final Long loadBalancerNo : targetLoadBalancerNos) { Runnable runnable = new Runnable() { @Override public void run() { LoggingUtils.setUserNo(user.getUserNo()); LoggingUtils.setUserName(user.getUsername()); LoggingUtils.setFarmNo(farm.getFarmNo()); LoggingUtils.setFarmName(farm.getFarmName()); try { loadBalancerProcess.start(loadBalancerNo); } catch (MultiCauseException ignore) { } catch (Throwable e) { log.error(e.getMessage(), e); // イベントログ出力 eventLogger.error("SystemError", new Object[] { e.getMessage() }); } finally { LoggingUtils.removeContext(); } } }; executorService.execute(runnable); } } // 処理中のロードバランサがある場合 if (processing) { return false; } return true; } protected boolean processStopLoadBalancer(final Farm farm) { // 無効なロードバランサを取得 List<LoadBalancer> loadBalancers = new ArrayList<LoadBalancer>(); List<LoadBalancer> allLoadBalancers = loadBalancerDao.readByFarmNo(farm.getFarmNo()); for (LoadBalancer loadBalancer : allLoadBalancers) { if (BooleanUtils.isNotTrue(loadBalancer.getEnabled())) { loadBalancers.add(loadBalancer); } } // 無効なロードバランサが無い場合 if (loadBalancers.isEmpty()) { return true; } // ロードバランサの状態を取得 boolean processing = false; List<Long> targetLoadBalancerNos = new ArrayList<Long>(); for (LoadBalancer loadBalancer : loadBalancers) { LoadBalancerStatus status = LoadBalancerStatus.fromStatus(loadBalancer.getStatus()); if (status != LoadBalancerStatus.STOPPED) { processing = true; if (status == LoadBalancerStatus.RUNNING || status == LoadBalancerStatus.WARNING) { targetLoadBalancerNos.add(loadBalancer.getLoadBalancerNo()); } } } // 起動しているロードバランサを停止する if (!targetLoadBalancerNos.isEmpty()) { final User user = userDao.read(farm.getUserNo()); for (final Long loadBalancerNo : targetLoadBalancerNos) { Runnable runnable = new Runnable() { @Override public void run() { LoggingUtils.setUserNo(user.getUserNo()); LoggingUtils.setUserName(user.getUsername()); LoggingUtils.setFarmNo(farm.getFarmNo()); LoggingUtils.setFarmName(farm.getFarmName()); try { loadBalancerProcess.stop(loadBalancerNo); } catch (MultiCauseException ignore) { } catch (Throwable e) { log.error(e.getMessage(), e); // イベントログ出力 eventLogger.error("SystemError", new Object[] { e.getMessage() }); } finally { LoggingUtils.removeContext(); } } }; executorService.execute(runnable); } } // 処理中のインスタンスがある場合 if (processing) { return false; } return true; } /** * instanceProcessを設定します。 * * @param instanceProcess instanceProcess */ public void setInstanceProcess(InstanceProcess instanceProcess) { this.instanceProcess = instanceProcess; } /** * componentProcessを設定します。 * * @param componentProcess componentProcess */ public void setComponentProcess(ComponentProcess componentProcess) { this.componentProcess = componentProcess; } /** * instancesProcessを設定します。 * * @param instancesProcess instancesProcess */ public void setInstancesProcess(InstancesProcess instancesProcess) { this.instancesProcess = instancesProcess; } /** * loadBalancerProcessを設定します。 * * @param loadBalancerProcess loadBalancerProcess */ public void setLoadBalancerProcess(LoadBalancerProcess loadBalancerProcess) { this.loadBalancerProcess = loadBalancerProcess; } /** * executorServiceを設定します。 * * @param executorService executorService */ public void setExecutorService(ExecutorService executorService) { this.executorService = executorService; } /** * eventLoggerを設定します。 * * @param eventLogger eventLogger */ public void setEventLogger(EventLogger eventLogger) { this.eventLogger = eventLogger; } }