content: // Licensed to the Apache Software Foundation (ASF) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The ASF licenses this file
  // to you under the Apache License, Version 2.0 (the
  // "License"); you may not use this file except in compliance
  // with the License.  You may obtain a copy of the License at
  //
  //   http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing,
  // software distributed under the License is distributed on an
  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  // KIND, either express or implied.  See the License for the
  // specific language governing permissions and limitations
  // under the License.
  package com.cloud.ha;
  
  import java.util.Date;
  import java.util.Map;
  import java.util.concurrent.TimeUnit;
  
  import javax.inject.Inject;
  import javax.naming.ConfigurationException;
  
  import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
  import org.apache.cloudstack.managed.context.ManagedContextRunnable;
  
  import com.cloud.alert.AlertManager;
  import com.cloud.usage.dao.UsageJobDao;
  import com.cloud.utils.db.TransactionLegacy;
  
  public class HighAvailabilityManagerExtImpl extends HighAvailabilityManagerImpl {
  
      @Inject
      UsageJobDao _usageJobDao;
  
      @Inject
      ConfigurationDao configDao;
  
      @Override
      public boolean configure(final String name, final Map<String, Object> xmlParams) throws ConfigurationException {
          super.configure(name, xmlParams);
          return true;
      }
  
      @Override
      public boolean start() {
          super.start();
  
          boolean enableUsage = new Boolean(configDao.getValue("enable.usage.server"));
  
          //By default, usage is enabled for production
          //Devs might override this value to disable usage in their setup
          if (enableUsage) {
              _executor.scheduleAtFixedRate(new UsageServerMonitorTask(), 60 * 60, 10 * 60, TimeUnit.SECONDS); // schedule starting in one hour to execute every 10 minutes
          }
  
          return true;
      }
  
      protected class UsageServerMonitorTask extends ManagedContextRunnable {
          @Override
          protected void runInContext() {
              if (logger.isInfoEnabled()) {
                  logger.info("checking health of usage server");
              }
  
              try {
                  boolean isRunning = false;
                  TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB);
                  try {
                      Date lastHeartbeat = _usageJobDao.getLastHeartbeat();
                      if (lastHeartbeat != null) {
                          long sinceLastHeartbeat = System.currentTimeMillis() - lastHeartbeat.getTime();
                          if (sinceLastHeartbeat <= (10 * 60 * 1000)) {
                              // if it's been less than 10 minutes since the last heartbeat, then it appears to be running, otherwise send an alert
                              isRunning = true;
                          }
                      }
                      if (logger.isDebugEnabled()) {
                          logger.debug("usage server running? " + isRunning + ", heartbeat: " + lastHeartbeat);
                      }
                  } finally {
                      txn.close();
  
                      // switch back to VMOPS db
                      TransactionLegacy swap = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
                      swap.close();
                  }
  
                  if (!isRunning) {
                      _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_USAGE_SERVER, 0, new Long(0), "No usage server process running",
                          "No usage server process has been detected, some attention is required");
                  } else {
                      _alertMgr.clearAlert(AlertManager.AlertType.ALERT_TYPE_USAGE_SERVER, 0, 0);
                  }
              } catch (Exception ex) {
                  logger.warn("Error while monitoring usage job", ex);
              }
          }
      }
  }
  