org.hyperic.hq.topn.TopNManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.topn.TopNManagerImpl.java

Source

/**
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 *  "derived work".
 *
 *  Copyright (C) [2013], VMware, Inc.
 *  This file is part of HQ.
 *
 *  HQ is free software; you can redistribute it and/or modify
 *  it under the terms version 2 of the GNU General Public License as
 *  published by the Free Software Foundation. This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 *  USA.
 *
 */
package org.hyperic.hq.topn;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.agent.AgentConnectionException;
import org.hyperic.hq.agent.AgentRemoteException;
import org.hyperic.hq.appdef.server.session.Platform;
import org.hyperic.hq.appdef.server.session.ResourceCreatedZevent;
import org.hyperic.hq.appdef.server.session.ResourceDeletedZevent;
import org.hyperic.hq.appdef.server.session.ResourceRefreshZevent;
import org.hyperic.hq.appdef.server.session.ResourceUpdatedZevent;
import org.hyperic.hq.appdef.server.session.ResourceZevent;
import org.hyperic.hq.appdef.shared.AppdefEntityID;
import org.hyperic.hq.appdef.shared.ConfigManager;
import org.hyperic.hq.appdef.shared.PlatformManager;
import org.hyperic.hq.authz.shared.AuthzSubjectManager;
import org.hyperic.hq.common.ApplicationException;
import org.hyperic.hq.common.shared.ServerConfigManager;
import org.hyperic.hq.hibernate.SessionManager;
import org.hyperic.hq.hibernate.SessionManager.SessionRunner;
import org.hyperic.hq.measurement.agent.client.MeasurementCommandsClient;
import org.hyperic.hq.measurement.agent.client.MeasurementCommandsClientFactory;
import org.hyperic.hq.measurement.agent.commands.ScheduleTopn_args;
import org.hyperic.hq.measurement.data.TopNConfigurationProperties;
import org.hyperic.hq.measurement.server.session.TopNSchedule;
import org.hyperic.hq.measurement.server.session.TopNScheduleDAO;
import org.hyperic.hq.measurement.shared.TopNManager;
import org.hyperic.hq.product.ProductPlugin;
import org.hyperic.hq.zevents.Zevent;
import org.hyperic.hq.zevents.ZeventEnqueuer;
import org.hyperic.hq.zevents.ZeventListener;
import org.hyperic.util.ConfigPropertyException;
import org.hyperic.util.config.ConfigResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.xerial.snappy.Snappy;

@Component
public class TopNManagerImpl implements ZeventListener<ResourceZevent>, TopNManager {

    public final static String TOPN_DEFAULT_INTERVAL = "TOPN_DEFAULT_INTERVAL";
    public final static String TOPN_NUMBER_OF_PROCESSES = "TOPN_NUMBER_OF_PROCESSES";
    private final Log log = LogFactory.getLog(TopNManagerImpl.class);
    private final ZeventEnqueuer zEventManager;
    private final PlatformManager platformManager;
    private final MeasurementCommandsClientFactory measurementCommandsClientFactory;
    private final ServerConfigManager serverConfigManager;
    private final AuthzSubjectManager authzSubjectManager;
    private final ConfigManager configManager;
    private final TopNScheduleDAO topNScheduleDao;

    @Autowired
    public TopNManagerImpl(ZeventEnqueuer zEventManager, PlatformManager platformManager,
            MeasurementCommandsClientFactory measurementCommandsClientFactory,
            ServerConfigManager serverConfigManager, AuthzSubjectManager authzSubjectManager,
            ConfigManager configManager, TopNScheduleDAO topNScheduleDao) {
        this.zEventManager = zEventManager;
        this.platformManager = platformManager;
        this.measurementCommandsClientFactory = measurementCommandsClientFactory;
        this.serverConfigManager = serverConfigManager;
        this.authzSubjectManager = authzSubjectManager;
        this.configManager = configManager;
        this.topNScheduleDao = topNScheduleDao;
    }

    @PostConstruct
    public void subscribe() {
        Set<Class<? extends Zevent>> listenEvents = new HashSet<Class<? extends Zevent>>();
        listenEvents.add(ResourceCreatedZevent.class);
        listenEvents.add(ResourceUpdatedZevent.class);
        listenEvents.add(ResourceRefreshZevent.class);
        listenEvents.add(ResourceDeletedZevent.class);
        zEventManager.addBufferedListener(listenEvents, this);
    }

    @Transactional
    public void scheduleTopNCollection(AppdefEntityID id, ConfigResponse config) {
        log.info("Rescheduling TopN collection for platform '" + id.getId()
                + "', since scheduling parameters has changed");
        Platform platform = platformManager.getPlatformById(id.getId());
        if (!isTopNSupported(platform)) {
            return;
        }
        if (!updateScheduleObject(config, platform.getResource().getId())) {
            return;
        }

        if (config.getValue(TopNConfigurationProperties.ENABLE_TOPN_COLLECTION.getName()) == null || !config
                .getValue(TopNConfigurationProperties.ENABLE_TOPN_COLLECTION.getName()).equalsIgnoreCase("true")) {
            unscheduleTopNCollection(platform.getResource().getId(), config);
            return;
        }
        scheduleTopNCollection(platform, config);
    }

    public int getNumberOfProcessesToShowForPlatform(int resourceId) {
        Platform platform = platformManager.getPlatformByResourceId(resourceId);
        ConfigResponse config;
        try {
            config = configManager.getMergedConfigResponse(authzSubjectManager.getOverlordPojo(),
                    ProductPlugin.TYPE_MEASUREMENT, platform.getEntityId(), true);
        } catch (Exception e) {
            return -1;
        }
        return Integer.valueOf(config.getValue(TopNConfigurationProperties.TOPN_NUMBER_OF_PROCESSES.getName()));
    }

    @Transactional
    public void scheduleTopNCollection(int resourceId, int intervalInMinutes, int numberOfProcesses) {
        ConfigResponse config;
        Platform platform = platformManager.getPlatformByResourceId(resourceId);
        if (!isTopNSupported(platform)) {
            return;
        }
        try {
            config = configManager.getMergedConfigResponse(authzSubjectManager.getOverlordPojo(),
                    ProductPlugin.TYPE_MEASUREMENT, platform.getEntityId(), true);
        } catch (Exception e) {
            return;
        }

        configureTopNSchedule(platform, config, intervalInMinutes, numberOfProcesses);
        scheduleTopNCollection(platform, config);
    }

    @Transactional
    public void updateGlobalTopNInterval(int intervalInMinutes) {
        log.info("Updating Top Processes interval in minutes for all platforms to '" + intervalInMinutes + "'");
        try {
            Properties newProps = serverConfigManager.getConfig();
            newProps.put(TOPN_DEFAULT_INTERVAL, String.valueOf(intervalInMinutes));
            serverConfigManager.setConfig(authzSubjectManager.getOverlordPojo(), newProps);
        } catch (ApplicationException e) {
            log.error("Error updating TopN interval", e);
            return;
        } catch (ConfigPropertyException e) {
            log.error("Error updating TopN interval", e);
            return;
        }
        for (TopNSchedule schedule : topNScheduleDao.findAll()) {
            scheduleTopNCollection(schedule.getResourceId(), intervalInMinutes, schedule.getNumberOfProcesses());
        }
    }

    @Transactional
    public void updateGlobalTopNNumberOfProcesses(int numberOfProcesses) {
        log.info("Updating number of processes to collect for all platforms to '" + numberOfProcesses + "'");
        try {
            Properties newProps = serverConfigManager.getConfig();
            newProps.put(TOPN_NUMBER_OF_PROCESSES, String.valueOf(numberOfProcesses));
            serverConfigManager.setConfig(authzSubjectManager.getOverlordPojo(), newProps);
        } catch (ApplicationException e) {
            log.error("Error updating TopN interval", e);
            return;
        } catch (ConfigPropertyException e) {
            log.error("Error updating TopN interval", e);
            return;
        }
        for (TopNSchedule schedule : topNScheduleDao.findAll()) {
            scheduleTopNCollection(schedule.getResourceId(), schedule.getIntervalInMinutes(), numberOfProcesses);
        }

    }

    @Transactional
    public void unscheduleGlobalTopNCollection() {
        log.info("Disabling Top Processes collection for all platforms");
        try {
            Properties newProps = serverConfigManager.getConfig();
            newProps.put(TOPN_DEFAULT_INTERVAL, "0");
            serverConfigManager.setConfig(authzSubjectManager.getOverlordPojo(), newProps);
        } catch (ApplicationException e) {
            log.error("Error unscheduling TopN collection", e);
            return;
        } catch (ConfigPropertyException e) {
            log.error("Error unscheduling TopN collection", e);
            return;
        }
        for (TopNSchedule schedule : topNScheduleDao.findAll()) {
            if (schedule.isEnabled()) {
                unscheduleTopNCollection(schedule.getResourceId());
            }
        }

    }

    @Transactional
    public void unscheduleTopNCollection(int resourceId) {
        unscheduleTopNCollection(resourceId, null);
    }

    @Transactional
    public void unscheduleTopNCollection(int resourceId, ConfigResponse config) {
        log.info("Unscheduling Top Processes collection for resource '" + resourceId + "'");
        Platform platform = platformManager.getPlatformByResourceId(resourceId);
        if (null == config) {
            try {
                config = configManager.getMergedConfigResponse(authzSubjectManager.getOverlordPojo(),
                        ProductPlugin.TYPE_MEASUREMENT, platform.getEntityId(), true);
            } catch (Exception e) {
                return;
            }
        }
        MeasurementCommandsClient client = measurementCommandsClientFactory.getClient(platform.getAgent());

        // Update ConfigResponse
        config.setValue(TopNConfigurationProperties.ENABLE_TOPN_COLLECTION.getName(), false);
        persistConfigResponse(platform, config);

        // Update the TopNSchedule object
        TopNSchedule scheduleData = topNScheduleDao.get(resourceId);
        scheduleData.setEnabled(false);
        scheduleData.setLastUpdated(System.currentTimeMillis());
        topNScheduleDao.save(scheduleData);

        // Send the unschedule command to the client
        try {
            client.unscheduleTopn();
        } catch (AgentRemoteException ex) {
            log.error("Error while unscheduling TopN", ex);
        } catch (AgentConnectionException ex) {
            log.error("Error while unscheduling TopN", ex);
        }
    }

    private void persistConfigResponse(Platform platform, ConfigResponse config) {
        try {
            configManager.setConfigResponse(authzSubjectManager.getOverlordPojo(), platform.getEntityId(), config,
                    ProductPlugin.TYPE_MEASUREMENT, false, false);
        } catch (Exception e) {

        }
    }

    public void processEvents(List<ResourceZevent> list) {
        for (final ResourceZevent e : list) {
            final AppdefEntityID id = e.getAppdefEntityID();
            if (!id.isPlatform()) {
                return;
            }
            try {
                SessionManager.runInSession(new SessionRunner() {
                    public void run() throws Exception {

                        if (e instanceof ResourceDeletedZevent) {
                            if (null != e.getResourceId()) {
                                TopNSchedule schedule = topNScheduleDao.get(e.getResourceId());
                                if (null != schedule) {
                                    if (log.isDebugEnabled()) {
                                        log.debug("Deleting TopNSchedule entry with id - '" + e.getResourceId()
                                                + "'");
                                    }
                                    topNScheduleDao.remove(schedule);
                                    topNScheduleDao.getSession().flush();
                                }
                            }
                            return;
                        }

                        Platform platform = platformManager.getPlatformById(id.getId());
                        if (!isTopNSupported(platform)) {
                            return;
                        }
                        if (Integer.valueOf(serverConfigManager.getPropertyValue(TOPN_DEFAULT_INTERVAL)) <= 0) {
                            if (log.isDebugEnabled()) {
                                log.debug("TopN collection is disabled, not scheduling for platform '"
                                        + platform.getFqdn() + "'");
                            }
                            return;
                        }

                        ConfigResponse config = configManager.getMergedConfigResponse(
                                authzSubjectManager.getOverlordPojo(), ProductPlugin.TYPE_MEASUREMENT, id, true);

                        if (e instanceof ResourceCreatedZevent) {
                            //Remove creation due to bug HQ-4786, we will create the object in ResourceUpdatedZevent
                            return;
                        }

                        else if (e instanceof ResourceUpdatedZevent) {
                            TopNSchedule schedule = topNScheduleDao.get(platform.getResource().getId());
                            if (null == schedule) {
                                configureDefaultTopNSchedule(platform, config);
                                log.info("Scheduling TopN collection for platform '"
                                        + platform.getResource().getId() + "'");
                                scheduleTopNCollection(platform, config);
                            } else {
                                int interval = Integer.valueOf(config.getValue(
                                        TopNConfigurationProperties.TOPN_COLLECTION_INTERVAL_IN_MINUTES.getName()));
                                int numberOfProcesses = Integer.valueOf(config
                                        .getValue(TopNConfigurationProperties.TOPN_NUMBER_OF_PROCESSES.getName()));
                                boolean enabled = Boolean.valueOf(config
                                        .getValue(TopNConfigurationProperties.ENABLE_TOPN_COLLECTION.getName()));
                                if ((interval != schedule.getIntervalInMinutes())
                                        || (numberOfProcesses != schedule.getNumberOfProcesses())
                                        || (enabled != schedule.isEnabled())) {

                                    topNScheduleDao.getSession().clear();
                                    scheduleTopNCollection(id, config);
                                }
                            }
                        }

                        else if (e instanceof ResourceRefreshZevent) {
                            TopNSchedule schedule = topNScheduleDao.get(platform.getResource().getId());
                            if ((null != schedule) && !schedule.isEnabled()) {
                                return;
                            }
                            log.info("Rescheduling TopN collection for platform '" + platform.getResource().getId()
                                    + "'");

                            if (null == schedule) {
                                configureDefaultTopNSchedule(platform, config);
                            }

                            scheduleTopNCollection(platform, config);
                        }

                    }

                    public String getName() {
                        return "TopNEventsListener";
                    }
                });
            } catch (Exception ex) {
                log.error(ex, ex);
                return;
            }

        }

    }

    private void configureDefaultTopNSchedule(Platform platform, ConfigResponse config) {
        if (log.isDebugEnabled()) {
            log.debug("Configuring ConfigResponse with default Top Processes parameters for platform '"
                    + platform.getName() + "'");
        }
        configureTopNSchedule(platform, config,
                Integer.valueOf(serverConfigManager.getPropertyValue(TOPN_DEFAULT_INTERVAL)),
                Integer.valueOf(serverConfigManager.getPropertyValue(TOPN_NUMBER_OF_PROCESSES)));
    }

    private boolean isTopNSupported(Platform platform) {
        if (null == platform) {
            return false;
        }
        if (!agentVersionValid(platform)) {
            return false;
        }
        if (!platform.getPlatformType().getPlugin().equalsIgnoreCase("system")) {
            return false;
        }
        return true;
    }

    private boolean agentVersionValid(Platform platform) {
        // TODO:Revisit this
        // TopN is supported only for agents with version >=
        // 5.8.0
        if (0 > platform.getAgent().getVersion().compareTo("5.8.0")) {
            if (log.isDebugEnabled()) {
                log.debug("The agent running on platform '" + platform.getName()
                        + "' version is older than 5.8, not schedulig Top Processes collection");
            }
            return false;
        }
        return true;
    }

    private void scheduleTopNCollection(Platform platform, ConfigResponse config) {
        if (!config.getValue(TopNConfigurationProperties.ENABLE_TOPN_COLLECTION.getName())
                .equalsIgnoreCase("true")) {
            return;
        }
        int interval = Integer.valueOf(
                config.getValue(TopNConfigurationProperties.TOPN_COLLECTION_INTERVAL_IN_MINUTES.getName()));
        int numberOfProcesses = Integer
                .valueOf(config.getValue(TopNConfigurationProperties.TOPN_NUMBER_OF_PROCESSES.getName()));

        MeasurementCommandsClient client = measurementCommandsClientFactory.getClient(platform.getAgent());
        try {
            client.scheduleTopn(new ScheduleTopn_args(interval, null, numberOfProcesses));
        } catch (AgentRemoteException ex) {
            log.error("Error while scheduling TopN", ex);
        } catch (AgentConnectionException ex) {
            log.error("Error while scheduling TopN", ex);
        }
    }

    private void configureTopNSchedule(Platform platform, ConfigResponse config, int interval,
            int numberOfProcesses) {
        config.setValue(TopNConfigurationProperties.ENABLE_TOPN_COLLECTION.getName(), true);
        config.setValue(TopNConfigurationProperties.TOPN_COLLECTION_INTERVAL_IN_MINUTES.getName(), interval);
        config.setValue(TopNConfigurationProperties.TOPN_NUMBER_OF_PROCESSES.getName(), numberOfProcesses);
        persistConfigResponse(platform, config);
        updateScheduleObject(platform.getResource().getId(), true, interval, numberOfProcesses);
    }

    private boolean updateScheduleObject(ConfigResponse config, int resourceId) {
        //Add default values
        String intervalValue = config
                .getValue(TopNConfigurationProperties.TOPN_COLLECTION_INTERVAL_IN_MINUTES.getName());
        String numberOfProcesseslValue = config
                .getValue(TopNConfigurationProperties.TOPN_NUMBER_OF_PROCESSES.getName());
        String enabledValue = config.getValue(TopNConfigurationProperties.ENABLE_TOPN_COLLECTION.getName());

        //In case of null values, dont crate schedule and return
        if (intervalValue == null || numberOfProcesseslValue == null || enabledValue == null) {
            return false;
        }
        int interval = Integer.valueOf(intervalValue);
        int numberOfProcesses = Integer.valueOf(numberOfProcesseslValue);
        boolean enabled = Boolean.valueOf(enabledValue);
        updateScheduleObject(resourceId, enabled, interval, numberOfProcesses);
        return true;
    }

    private void updateScheduleObject(int resourceId, boolean enabled, int interval, int numberOfProcesses) {
        if (log.isDebugEnabled()) {
            log.debug("Updating 'TopNSchedule' object with the following attributes - resourceId='" + resourceId
                    + ", enabled='" + enabled + "', interval='" + interval + "', numberOfProcesses='"
                    + numberOfProcesses + "'");

        }

        TopNSchedule schedule = topNScheduleDao.get(resourceId);
        if (schedule == null) {
            schedule = new TopNSchedule();
        }

        schedule.setResourceId(resourceId);
        schedule.setLastUpdated(System.currentTimeMillis());
        schedule.setIntervalInMinutes(interval);
        schedule.setNumberOfProcesses(numberOfProcesses);
        schedule.setEnabled(enabled);
        topNScheduleDao.save(schedule);
    }

    public byte[] compressData(final byte[] data) {
        try {
            return Snappy.compress(data);
        } catch (final IOException e) {
            log.error("Unable to compress TopN data " + e.getClass().getSimpleName(), e);
            return data;
        }
    }

    public byte[] uncompressData(final byte[] data) {
        try {
            return Snappy.uncompress(data);
        } catch (final IOException e) {
            log.error("Unable to uncompress TopN data " + e.getClass().getSimpleName(), e);
            return data;
        }
    }
}