2 Replies Latest reply on Jul 18, 2011 5:33 PM by Sara Stewart

    Custom event plugin

    Sara Stewart Newbie

      Hi, everyone,

         I am new to RHQ and have run into a problem creating a custom plugin that monitors log file output.

      I keep getting this error (Please note that I changed some of the text fields to be generic names and removed the package line that was at the top of each java file):

      "An unexpected error occurred in the Agent.  Cause:  org.rhq.core.clientapi.agent.PuginContainerException:  The [text] plugin does not properly support manual addition of [text] Resources." 

       

          I am using RHQ 3.0.0.

       

           Here is my rhq-plugin.xml:

      <?xml version="1.0" encoding="UTF-8" ?>

      <plugin name="plugin2" displayName="plugin2"
      description="Counts files in a directory" package="plugin2"
      xmlns:xsi="
      http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:xmlns:rhq-plugin"
      xmlns:c="urn:xmlns:rhq-configuration">

      <service name="plugin service 2" discovery="CountDiscovery" class="CountComponent"
        singleton="false" supportsManualAdd="true">
      <plugin-configuration>
         <c:simple-property name="directory" displayName="Directory To Monitor"
          required="true"
          description="A file path to monitor for the number of files.  Example:  C:\Temp" />
        </plugin-configuration>
        <operation name="dummyOperation" displayName="dummyOperation"
         description="Purges all files from the directory.">
         <results>
          <c:simple-property name="totalFiles" description="Total number of files." />
          <c:simple-property name="totalFilesDeleted"
           description="Number of files deleted." />
          <c:simple-property name="totalFilesRemain"
           description="Number of files unable to delete." />
         </results>
        </operation>

        <metric property="dummyMetric" displayName="dummyMetric"
         dataType="trait" displayType="summary" defaultOn="true" defaultInterval="120000" />

        <event name="RHEVMDummyEvent" />

      </service>

      </plugin>

       

      The CountComponent looks like this:

      import java.util.HashSet;
      import java.util.Set;
      import java.io.File;

      import org.apache.commons.logging.Log;
      import org.apache.commons.logging.LogFactory;

      import org.rhq.core.domain.configuration.Configuration;
      import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
      import org.rhq.core.domain.measurement.AvailabilityType;
      import org.rhq.core.domain.measurement.MeasurementDataNumeric;
      import org.rhq.core.domain.measurement.MeasurementReport;
      import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
      import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
      import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
      import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet;
      import org.rhq.core.pluginapi.inventory.CreateResourceReport;
      import org.rhq.core.pluginapi.inventory.DeleteResourceFacet;
      import org.rhq.core.pluginapi.inventory.ResourceComponent;
      import org.rhq.core.pluginapi.inventory.ResourceContext;
      import org.rhq.core.pluginapi.measurement.MeasurementFacet;
      import org.rhq.core.pluginapi.event.EventContext;
      import org.rhq.core.pluginapi.operation.OperationContext;
      import org.rhq.core.pluginapi.operation.OperationFacet;
      import org.rhq.core.pluginapi.operation.OperationResult;
      import org.rhq.core.pluginapi.plugin.PluginContext;
      import org.rhq.core.pluginapi.plugin.PluginLifecycleListener;
      import org.rhq.core.pluginapi.support.SnapshotReportRequest;
      import org.rhq.core.pluginapi.support.SnapshotReportResults;
      import org.rhq.core.pluginapi.support.SupportFacet;


      public class CountComponent implements ResourceComponent
      , MeasurementFacet
      , OperationFacet
      , ConfigurationFacet
      , CreateChildResourceFacet
      , DeleteResourceFacet
      , PluginLifecycleListener
      , SupportFacet
      {
          private final Log log = LogFactory.getLog(this.getClass());

          private static final int CHANGEME = 1; // TODO remove or change this
      private File dir;

          public static final String DUMMY_EVENT = "RHEVMDummyEvent"; // Same as in Plugin-Descriptor

          EventContext eventContext;

          /**
           * Callback when the plugin is created
           * @see org.rhq.core.pluginapi.plugin.PluginLifecycleListener#initialize(PluginContext)
           */
          public void initialize(PluginContext context) throws Exception
          {
          }

          /**
           * Callback when the plugin is unloaded
           * @see org.rhq.core.pluginapi.plugin.PluginLifecycleListener#shutdown()
           */
          public void shutdown()
          {
          }

          /**
           * Return availability of this resource
           *  @see org.rhq.core.pluginapi.inventory.ResourceComponent#getAvailability()
           */
          public AvailabilityType getAvailability() {
              // TODO supply real implementation
              return AvailabilityType.UP;
          }


          /**
           * Start the resource connection
           * @see org.rhq.core.pluginapi.inventory.ResourceComponent#start(org.rhq.core.pluginapi.inventory.ResourceContext)
           */
          public void start(ResourceContext context) throws InvalidPluginConfigurationException, Exception {

              Configuration conf = context.getPluginConfiguration();
              // TODO add code to start the resource / connection to it
              dir = new File(context.getResourceKey());

              eventContext = context.getEventContext();
              RHEVMEventPoller eventPoller = new RHEVMEventPoller();
              eventContext.registerEventPoller(eventPoller, 60);

          }


          /**
           * Tear down the rescource connection
           * @see org.rhq.core.pluginapi.inventory.ResourceComponent#stop()
           */
          public void stop() {


              eventContext.unregisterEventPoller(DUMMY_EVENT);
          }

       

          /**
           * Gather measurement data
           *  @see org.rhq.core.pluginapi.measurement.MeasurementFacet#getValues(org.rhq.core.domain.measurement.MeasurementReport, java.util.Set)
           */
          public  void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {

               for (MeasurementScheduleRequest req : metrics) {
                  if (req.getName().equals("dummyMetric")) {
                     //  MeasurementDataNumeric res = new MeasurementDataNumeric(req, Double.valueOf(CHANGEME));
                     //  report.addData(res);
                  }
                  // TODO add more metrics here
               }
          }

       

          public void startOperationFacet(OperationContext context) {

          }


          /**
           * Invokes the passed operation on the managed resource
           * @param name Name of the operation
           * @param params The method parameters
           * @return An operation result
           * @see org.rhq.core.pluginapi.operation.OperationFacet
           */
          public OperationResult invokeOperation(String name, Configuration params) throws Exception {

              OperationResult res = new OperationResult();
              if ("dummyOperation".equals(name)) {
                  // TODO implement me

              }
              return res;
          }


          /**
           * Load the configuration from a resource into the configuration
           * @return The configuration of the resource
           * @see org.rhq.core.pluginapi.configuration.ConfigurationFacet
           */
          public Configuration loadResourceConfiguration()
          {
              // TODO supply code to load the configuration from the resource into the plugin
              return null;
          }

          /**
           * Write down the passed configuration into the resource
           * @param report The configuration updated by the server
           * @see org.rhq.core.pluginapi.configuration.ConfigurationFacet
           */
          public void updateResourceConfiguration(ConfigurationUpdateReport report)
          {
              // TODO supply code to update the passed report into the resource
          }

          /**
           * Create a child resource
           * @see org.rhq.core.pluginapi.inventory.CreateChildResourceFacet
           */
          public CreateResourceReport createResource(CreateResourceReport report)
          {
              // TODO supply code to create a child resource

              return null; // TODO change this
          }

          /**
           * Delete a child resource
           * @see org.rhq.core.pluginapi.inventory.DeleteResourceFacet
           */
          public void deleteResource() throws Exception
          {
              // TODO supply code to delete a child resource
          }

          /**
           * Takes a snapshot and returns the snapshot report content in the given stream. A facet implementation
           * can support different kinds of snapshots, the given name determines which kind of snapshot to take.
           *
           * @param request identifies the type of snapshot to take
           * @return snapshot results, including a stream containing the contents of the snapshot report
           * @throws Exception if failed to generate the snapshot report
           */
          public SnapshotReportResults getSnapshotReport(SnapshotReportRequest request) throws Exception
          {
              // TODO
              return null;
          }
      }

       

      The Discovery looks like this:

      import java.util.Collections;
      import java.util.HashSet;
      import java.util.List;
      import java.util.Set;
      import org.apache.commons.logging.Log;
      import org.apache.commons.logging.LogFactory;
      import org.rhq.core.domain.configuration.Configuration;
      import org.rhq.core.domain.configuration.Property;
      import org.rhq.core.domain.configuration.PropertySimple;
      import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
      import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
      import org.rhq.core.pluginapi.inventory.ManualAddFacet;
      import org.rhq.core.pluginapi.inventory.ProcessScanResult;
      import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
      import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;


      /**
      * Discovery class
      */
      public class CountDiscovery implements ResourceDiscoveryComponent
      ,ManualAddFacet
      {

          private final Log log = LogFactory.getLog(this.getClass());

          /**
           * This method is an empty dummy, as you have selected manual addition
           * in the plugin generator.
           * If you want to have auto discovery too, remove the "return emptySet"
           * and implement the auto discovery logic.
           */
          public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext discoveryContext) throws Exception {
              return Collections.emptySet();
              }

            /**
             * Do the manual add of this one resource
             */
            public DiscoveredResourceDetails discoverResource(Configuration pluginConfiguration, ResourceDiscoveryContext context) throws InvalidPluginConfigurationException {

                  // TODO implement this
                  DiscoveredResourceDetails detail = null; // new DiscoveredResourceDetails(
      //                context.getResourceType(), // ResourceType
      //            );

                  return detail;
            }
      }

       

      And the RHEVMEventPoller looks like this:

      import java.util.HashSet;
      import java.util.Set;

      import org.rhq.core.domain.event.Event;
      import org.rhq.core.domain.event.EventSeverity;
      import org.rhq.core.pluginapi.event.EventPoller;
      import org.apache.commons.logging.Log;
      import org.apache.commons.logging.LogFactory;

      public class RHEVMEventPoller implements EventPoller {
      private final Log log = LogFactory.getLog(this.getClass());

          public RHEVMEventPoller() {

          }


          /** Return the type of events we handle
           * @see org.rhq.core.pluginapi.event.EventPoller#getEventType()
           */
          public String getEventType() {
              return CountComponent.DUMMY_EVENT;
          }


          /** Return collected events
           * @see org.rhq.core.pluginapi.event.EventPoller#poll()
           */
          public Set<Event> poll() {
              Set<Event> eventSet = new HashSet<Event>();
              // TODO add your events here. Below is an example that
              /*
              synchronized (events) {
                  eventSet.addAll(events);
                  events.clear();
              }
              */
              log.warn("Polling Polling");

              return eventSet;
          }

      }

       

      Thanks in advance,

      Sara

        • 1. Re: Custom event plugin
          mazz Master

          what happened is your plugin component didn't return any details for a manually added resource that the user wanted to add - you returned null.

           

          looking at your code, this is what is happening:

           

                public DiscoveredResourceDetails discoverResource(Configuration pluginConfiguration, ResourceDiscoveryContext context) throws InvalidPluginConfigurationException {

                      // TODO implement this
                      DiscoveredResourceDetails detail = null; // new DiscoveredResourceDetails(
          //                context.getResourceType(), // ResourceType
          //            );

                      return detail;

           

          Once you return a non-null details object, you shouldn't see this error.

           

          You need to return a non-null object or throw an exception if the given plugin configuration values provided by the user are invalid.

           

          Side note: in later versions of RHQ, we introduced a new ManualAddFacet that your discovery component should implement to support manual addition of resources. But for your version, you don't need that.

          • 2. Re: Custom event plugin
            Sara Stewart Newbie

            Thanks!  The plugin deployed just fine to RHQ after the update.  Much appreciated.