diff --git a/clc/.classpath b/clc/.classpath index 6e7dd8c4bf5..896a5039d4e 100644 --- a/clc/.classpath +++ b/clc/.classpath @@ -1,191 +1,168 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clc/Makefile b/clc/Makefile index 8ba0480a219..9d2afbaa23f 100644 --- a/clc/Makefile +++ b/clc/Makefile @@ -9,6 +9,7 @@ web_prop_dir = ${TOP}/clc/modules/www/conf .PHONY: all build update_properties update_theme deps extras install all: deps build +test: deps build-test deps: @$(ANT) deps @@ -71,6 +72,20 @@ build-test: deps extras @make -C modules/storage-san/native @make -C modules/bootstrap +build-test: deps extras + @# we need JAVA_HOME + @if test -z "${JAVA_HOME}" ; then \ + echo "You need to define JAVA_HOME!"; exit 1; fi +# this causes problems for pbuilder, should be handled by configure and build.xml already +# @if test ! -e deps/cloud-lib.tar.gz; then \ +# echo "Cannot find java deps, please run 'make deps' in the 'clc/' subdirectory."; exit 1; fi + @ANT_OPTS="-Xmx1g -XX:MaxPermSize=512m" $(ANT) build-test-all + @ANT_OPTS="-Xmx1g -XX:MaxPermSize=512m" $(ANT) generate-bind + @ANT_OPTS="-Xmx1g -XX:MaxPermSize=512m" $(ANT) compile-bind + @ANT_OPTS="-Xmx1g -XX:MaxPermSize=512m" $(ANT) jar + @make -C modules/storage-controller/native + @make -C modules/bootstrap + clean: $(ANT) clean make -C modules/bootstrap clean @@ -83,8 +98,13 @@ distclean: clean make -C modules/storage-controller/native distclean make -C modules/storage-san/native distclean +install-test: build-test + @ANT_OPTS="-Xmx1g -XX:MaxPermSize=512m" $(ANT) install + @make -C modules/storage-controller/native install + @make -C modules/bootstrap install + install: build - @ANT_OPTS="-Xmx1g -XX:MaxPermSize=256m" $(ANT) install + @ANT_OPTS="-Xmx1g -XX:MaxPermSize=512m" $(ANT) install @make -C modules/storage-controller/native install @make -C modules/storage-san/native install @make -C modules/bootstrap install diff --git a/clc/build.xml b/clc/build.xml index adaddd1118d..bd0b1ba6182 100644 --- a/clc/build.xml +++ b/clc/build.xml @@ -94,56 +94,58 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - + + + + + + + + + @@ -190,9 +192,9 @@ - + diff --git a/clc/modules/core/src/main/java/com/eucalyptus/upgrade/StandalonePersistence.java b/clc/modules/core/src/main/java/com/eucalyptus/upgrade/StandalonePersistence.java index 8d05cdb437a..49274eb9416 100644 --- a/clc/modules/core/src/main/java/com/eucalyptus/upgrade/StandalonePersistence.java +++ b/clc/modules/core/src/main/java/com/eucalyptus/upgrade/StandalonePersistence.java @@ -191,8 +191,8 @@ static void setupSystemProperties( ) { newLibDir = getAndCheckLibDirectory( eucaHome ); } - public static void setupConfigurations( ) { - ServiceJarDiscovery.runDiscovery( new ComponentDiscovery( ) ); + static void setupConfigurations( ) { + ServiceJarDiscovery.doSingleDiscovery( new ComponentDiscovery( ) ); } private static File getAndCheckLibDirectory( String eucaHome ) { diff --git a/clc/modules/module-inc.xml b/clc/modules/module-inc.xml index a0066e19155..52d16bd10a3 100644 --- a/clc/modules/module-inc.xml +++ b/clc/modules/module-inc.xml @@ -182,6 +182,22 @@ + + + + + + + + + + + + + + + + diff --git a/clc/modules/msgs/src/main/java/com/eucalyptus/bootstrap/ServiceJarDiscovery.java b/clc/modules/msgs/src/main/java/com/eucalyptus/bootstrap/ServiceJarDiscovery.java index b7ab4c2f78a..330a396734c 100644 --- a/clc/modules/msgs/src/main/java/com/eucalyptus/bootstrap/ServiceJarDiscovery.java +++ b/clc/modules/msgs/src/main/java/com/eucalyptus/bootstrap/ServiceJarDiscovery.java @@ -84,6 +84,23 @@ private static void doDiscovery( ) { ServiceJarDiscovery.runDiscovery( ); } + public static void doSingleDiscovery( ServiceJarDiscovery s ) { + File libDir = new File( BaseDirectory.LIB.toString( ) ); + for ( File f : libDir.listFiles( ) ) { + if ( f.getName( ).startsWith( "eucalyptus" ) && f.getName( ).endsWith( ".jar" ) + && !f.getName( ).matches( ".*-ext-.*" ) ) { + LOG.debug( "Found eucalyptus component jar: " + f.getName( ) ); + try { + ServiceJarDiscovery.processFile( f ); + } catch ( Throwable e ) { + LOG.error( e.getMessage( ) ); + continue; + } + } + } + ServiceJarDiscovery.runDiscovery( s ); + } + public static void checkUniqueness( Class c ) { if ( classList.get( c ).size( ) > 1 ) { diff --git a/clc/modules/msgs/src/main/java/com/eucalyptus/bootstrap/SystemBootstrapper.java b/clc/modules/msgs/src/main/java/com/eucalyptus/bootstrap/SystemBootstrapper.java index 2fb1fa6886b..af036ca6e05 100644 --- a/clc/modules/msgs/src/main/java/com/eucalyptus/bootstrap/SystemBootstrapper.java +++ b/clc/modules/msgs/src/main/java/com/eucalyptus/bootstrap/SystemBootstrapper.java @@ -131,6 +131,18 @@ public boolean init( ) throws Exception { System.setProperty( "euca.log.exhaustive.user", "TRACE" ); System.setProperty( "euca.log.exhaustive.user", "TRACE" ); } + + /* This is a workaround for log4j brain damage which prevented the + * ActiveMQ broker from working properly. + */ + try { + //GroovyUtil.eval("com.eucalyptus.reporting.queue.QueueBroker.getInstance().startup()"); + LOG.info("Groovy eval of queue factory startup succeeded."); + } catch (Exception ex) { + LOG.error("Groovy eval of queue factory startup failed.", ex); + } + + System.setOut( new PrintStream( System.out ) { public void print( final String string ) { if ( string.replaceAll( "\\s*", "" ).length( ) > 2 ) { @@ -138,7 +150,12 @@ public void print( final String string ) { } } } + + + ); + + System.setErr( new PrintStream( System.err ) { public void print( final String string ) { if ( string.replaceAll( "\\s*", "" ).length( ) > 2 ) { @@ -147,6 +164,7 @@ public void print( final String string ) { } } ); + LOG.info( LogUtil.subheader( "Starting system with debugging set as: " + Join.join( "\n", LogLevels.class.getDeclaredFields( ) ) ) ); try { Logger.getLogger( "com.eucalyptus.entities.EntityWrapper" ).fatal( "Starting up" ); diff --git a/clc/modules/msgs/src/main/java/com/eucalyptus/component/ComponentDiscovery.java b/clc/modules/msgs/src/main/java/com/eucalyptus/component/ComponentDiscovery.java index 66254308a0c..6ee15bc015a 100644 --- a/clc/modules/msgs/src/main/java/com/eucalyptus/component/ComponentDiscovery.java +++ b/clc/modules/msgs/src/main/java/com/eucalyptus/component/ComponentDiscovery.java @@ -76,11 +76,15 @@ public boolean processClass( Class candidate ) throws Throwable { if ( ComponentId.class.isAssignableFrom( candidate ) && !Modifier.isAbstract( candidate.getModifiers( ) ) && !Modifier.isInterface( candidate.getModifiers( ) ) && !Any.class.equals( candidate ) ) { try { + LOG.info( "Found ComponentId of type: " + candidate.getCanonicalName() ); ComponentId id = ( ComponentId ) candidate.newInstance( ); ComponentIds.register( id ); + LOG.info( "-> Registering ComponentId of type: " + candidate.getCanonicalName() ); Components.create( id ); + } catch ( Throwable ex ) { LOG.error( ex, ex ); + LOG.info( "Error occurred while trying to register ComponentId of type: " + ex.getMessage(), ex ); } return true; } else { diff --git a/clc/modules/msgs/src/main/java/com/eucalyptus/system/SubDirectory.java b/clc/modules/msgs/src/main/java/com/eucalyptus/system/SubDirectory.java index 61af4eee3a6..294b4244a42 100644 --- a/clc/modules/msgs/src/main/java/com/eucalyptus/system/SubDirectory.java +++ b/clc/modules/msgs/src/main/java/com/eucalyptus/system/SubDirectory.java @@ -83,6 +83,7 @@ public enum SubDirectory { UPGRADE( BaseDirectory.CONF, "upgrade" ), REPORTS( BaseDirectory.CONF, "reports" ), CONF( BaseDirectory.CONF, "conf" ), + QUEUE( BaseDirectory.VAR, "queue" ), LIB( BaseDirectory.HOME, "/usr/share/eucalyptus" ); private static Logger LOG = Logger.getLogger( SubDirectory.class ); BaseDirectory parent; diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/GenerateReport.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/GenerateReport.java index 154d2fccad4..ded239c0bc4 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/GenerateReport.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/GenerateReport.java @@ -29,6 +29,13 @@ import com.eucalyptus.reporting.storage.StorageDisplayDb; import com.eucalyptus.reporting.units.Units; +/** + *

GenerateReport is a command-line tool for rapid testing which uses + * jasper reports internally. It takes command-line args from the + *

runTest.sh
mechanism and writes a resultant report to a file. + * + * @author tom.werges + */ public class GenerateReport { public static enum Format @@ -62,6 +69,8 @@ public String getFileExtension() } + /* Expects jrxml files to be in /tmp and writes results there. + */ private static File baseDir = new File("/tmp/"); private static File storageReportFile = new File(baseDir, "storage.jrxml"); private static File nestedStorageReportFile = new File(baseDir, "nested_storage.jrxml"); diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/ReportingBootstrapper.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/ReportingBootstrapper.java index 21535f9cc51..d5918d4b81d 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/ReportingBootstrapper.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/ReportingBootstrapper.java @@ -1,7 +1,6 @@ package com.eucalyptus.reporting; -import java.util.Timer; -import java.util.TimerTask; +import java.util.*; import org.apache.log4j.*; @@ -9,6 +8,7 @@ import com.eucalyptus.bootstrap.Bootstrapper; import com.eucalyptus.bootstrap.Provides; import com.eucalyptus.bootstrap.RunDuring; +import com.eucalyptus.component.*; import com.eucalyptus.component.id.Reporting; import com.eucalyptus.reporting.instance.*; import com.eucalyptus.reporting.storage.*; @@ -32,6 +32,7 @@ public class ReportingBootstrapper public ReportingBootstrapper() { + this.instanceListener = null; } @Override @@ -75,12 +76,15 @@ public boolean load() public boolean start() { try { - //TODO: brokers must FIND EACH OTHER here... + /* Start queue broker */ + QueueBroker.getInstance().startup(); + log.info("Queue broker started"); + queueFactory = QueueFactory.getInstance(); - //QueueFactory has been started in SystemBootstrapper.init() + queueFactory.startup(); /* Start storage receiver and storage queue poller thread */ @@ -101,7 +105,12 @@ public void run() */ QueueReceiver instanceReceiver = queueFactory.getReceiver(QueueIdentifier.INSTANCE); - instanceListener = new InstanceEventListener(); + if (instanceListener == null) { + instanceListener = new InstanceEventListener(); + log.info("New instance listener instantiated"); + } else { + log.info("Used existing instance listener"); + } instanceReceiver.addEventListener(instanceListener); log.info("ReportingBootstrapper started"); @@ -142,4 +151,10 @@ public boolean stop() } } + public void setOverriddenInstanceEventListener( + InstanceEventListener overriddenListener) + { + this.instanceListener = overriddenListener; + } + } diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceDisplayBean.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceDisplayBean.java index 28e0802f987..426faef164d 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceDisplayBean.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceDisplayBean.java @@ -97,5 +97,10 @@ public Long getDiskIoSize() return UnitUtil.convertSize(summary.getDiskIoMegs(), INTERNAL_UNITS.getSizeUnit(), units.getSizeUnit()); } + + public Units getUnits() + { + return units; + } } diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceEventListener.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceEventListener.java index 17174b1f7ea..d63dbea3368 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceEventListener.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceEventListener.java @@ -2,7 +2,6 @@ import java.util.*; -import org.hibernate.*; import org.apache.log4j.*; import com.eucalyptus.entities.EntityWrapper; @@ -56,17 +55,18 @@ public void fireEvent( Event e ) * already. */ if (! recentlySeenUuids.contains(uuid)) { - try { - entityWrapper.getUnique( new InstanceAttributes( ) { - { - setUuid( uuid ); - } - } ); - } catch ( Exception ex ) { - entityWrapper.add(insAttrs); - log.info("Wrote Reporting Instance:" + uuid); - } - recentlySeenUuids.add(uuid); + try { + entityWrapper.getUnique(new InstanceAttributes() + { + { + setUuid(uuid); + } + }); + } catch (Exception ex) { + entityWrapper.add(insAttrs); + log.info("Wrote Reporting Instance:" + uuid); + } + recentlySeenUuids.add(uuid); } /* Gather all usage snapshots, and write them all to the database diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageLog.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageLog.java index 0a0f1e9fea8..2577b255838 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageLog.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageLog.java @@ -6,6 +6,8 @@ import java.util.List; import java.util.Map; import org.apache.log4j.Logger; +import org.hibernate.Session; + import com.eucalyptus.configurable.ConfigurableClass; import com.eucalyptus.entities.EntityWrapper; import com.eucalyptus.reporting.GroupByCriterion; @@ -18,8 +20,8 @@ *

The data in the log is not indexed, in order to minimize write time. * As a result, you can't search through the log for specific instances or * specific data; you can only get a full dump between dates. However, there - * exist groovy scripts to filter the data, or to transfer the data into a - * data warehouse for subsequent searching. + * exist groovy scripts to transfer the data into a data warehouse for + * subsequent searching. * *

The usage data in logs is sampled, meaning data is collected * every n seconds and written. As a result, some small error will @@ -55,14 +57,18 @@ public static synchronized InstanceUsageLog getInstanceUsageLog() } /** - *

Scans through the usage log, then summarizes and groups the data it finds. - * For example, if you provide the criterion of "user", in scans through the usage - * log and adds up all usage data for each user, then returns a Map of - * UserId:UsageSummary. + *

Scans through the usage log, then summarizes the data it finds. + * Returns a map of instance usage, keyed by the value of the criterion you + * specified. For example, if you provide the criterion of "user", it scans + * through the usage log and adds up all usage data for each user, then + * returns a Map of UserId (String) -> UsageSummary. + * + *

This method is used for generating visual reports. For example, it + * could be used to generate a report of user id's in a left column with + * usage stats in various right-hand cols. * * @return A summary of all usage and instance data for a given criterion - * keyed by the criterion value. For example, a summary of all instance - * and usage data for each user, keyed by user. + * keyed by the criterion value. */ public Map scanSummarize(Period period, GroupByCriterion criterion) @@ -94,7 +100,10 @@ public Map scanSummarize(Period period, *

Scans through the usage log, then summarizes and groups the data it finds. * For example, scans through the usage log and adds up all usage data * for each user, within each Availability Zone, then returns the results - * as

AvailZone->UserId->UsageSummary
. + * as
AvailZoneId->UserId->UsageSummary
. + * + *

This is used to generate nested reports in which we list (for example) + * usage by user, grouped by availability zone. * * @return A summary of all usage and instance data for given criteria * keyed by the criterion values. @@ -150,6 +159,12 @@ private static String getAttributeValue(GroupByCriterion criterion, InstanceAttr } } + /** + *

LogScanResult is conceptually similar to a ResultSet. It contains the + * instance data and usage data for a particular period. + * + * @author tom.werges + */ public class LogScanResult { private final InstanceAttributes insAttrs; @@ -181,7 +196,8 @@ public UsageData getUsageData() } /** - *

Scans log for all results during some period. + *

Scans log for all results during some period. This method is used + * internally by the scanSummarize methods. */ public List scanLog(Period period) { diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageSnapshot.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageSnapshot.java index bb51680b8d8..dc1ca16c000 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageSnapshot.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageSnapshot.java @@ -6,8 +6,7 @@ *

InstanceUsageSnapshot is a record of cumulative instance resource usage * at a certain point in time, keyed by instance uuid. * - *

InstanceUsageSnapshot allows null values for some of its fields. Null values - * indicate unknown usage and not zero usage. + *

InstanceUsageSnapshot allows null values for some of its fields. * * @author tom.werges */ diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageSummary.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageSummary.java index b925de4027f..7ee6683b76e 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageSummary.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/InstanceUsageSummary.java @@ -3,12 +3,10 @@ import com.eucalyptus.reporting.Period; /** - *

UsageSummary is a summary of all resource usage for some entity over a - * single time period. An entity can be a user, a group, an account, an - * availability zone, a cluster, and so on. UsageSummary includes instance - * types, instance running times, and resource usage. UsageSummary includes - * everything in a single bean which is necessary to generate a jasper - * report of instance usage. + *

InstanceUsageSummary is a summary of all resource usage for some entity + * over a time period. It includes summations of the instance types, + * numbers, running times, resource usage, etc, for a given user, + * account or other entity. * * @author tom.werges */ diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/UsageData.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/UsageData.java index 72516d87abd..3f2b8dfdd99 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/UsageData.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/UsageData.java @@ -2,7 +2,7 @@ /** *

UsageData represents usage of resources (like disk bandwidth, etc) - * by an instance over some period. UsageData is immutable. + * by an instance over a single period. UsageData is immutable. * *

Null values for a field indicate unknown usage, not zero usage. * diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/UsageSnapshot.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/UsageSnapshot.java index eea41194263..292214c3ed7 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/UsageSnapshot.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/instance/UsageSnapshot.java @@ -1,7 +1,7 @@ package com.eucalyptus.reporting.instance; /** - * Snapshot of the resource usage of some instance at some point in time. + * UsageSnapshot of the resource usage of some instance at some point in time. * Contains cumulative usage data so it's populated with * all resource usage which has occurred up until this snapshot was * instantiated. diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/queue/QueueBootstrapper.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/queue/QueueBootstrapper.java index 9fc5f469c92..8116c64e196 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/queue/QueueBootstrapper.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/queue/QueueBootstrapper.java @@ -15,14 +15,18 @@ public class QueueBootstrapper extends Bootstrapper @Override public boolean load() throws Exception { - try { - QueueFactory.getInstance().startup(); - log.info("broker started"); - return true; - } catch (Exception ex) { - ex.printStackTrace(); - return false; - } + /* NOTE: a workaround was moved to SystemBootstrapper.init() because + * log4j brain damage prevents ActiveMQ broker from starting. + */ +// try { +// QueueFactory.getInstance().startup(); +// log.info("broker started"); +// return true; +// } catch (Exception ex) { +// ex.printStackTrace(); +// return false; +// } + return true; } @Override diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/queue/QueueBroker.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/queue/QueueBroker.java index 4ec767766be..656dc838b7d 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/queue/QueueBroker.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/queue/QueueBroker.java @@ -1,29 +1,25 @@ package com.eucalyptus.reporting.queue; -import java.util.ArrayList; -import java.util.List; +import java.util.*; + import org.apache.activemq.broker.BrokerService; import org.apache.activemq.command.ActiveMQDestination; import org.apache.log4j.*; +import com.eucalyptus.component.*; +import com.eucalyptus.component.id.Reporting; +import com.eucalyptus.system.SubDirectory; + public class QueueBroker { private static Logger log = Logger.getLogger( QueueBroker.class ); public static final String DEFAULT_NAME = "reportingBroker"; - public static final String DEFAULT_DIR = "/tmp"; - public static final String DEFAULT_URL = "tcp://localhost:63636"; + public static final String DEFAULT_DIR = SubDirectory.QUEUE.toString(); + public static final int DEFAULT_PORT = 63636; + public static final String DEFAULT_URL = "tcp://localhost:" + DEFAULT_PORT; + public static final String DEFAULT_REMOTE_URL_FORMAT = "static:(tcp://%s:%d)"; - private static QueueBroker instance = null; - - public static QueueBroker getInstance() - { - if (instance == null) { - instance = new QueueBroker(DEFAULT_NAME, DEFAULT_URL, DEFAULT_DIR); - } - return instance; - } - private boolean started = false; private String brokerName; @@ -43,6 +39,17 @@ private QueueBroker(String brokerName, String brokerUrl, String brokerDataDir) this.destinations = new ArrayList(); } + private static QueueBroker instance; + + public static QueueBroker getInstance() + { + if (instance == null) { + return instance = new QueueBroker(DEFAULT_NAME, DEFAULT_URL, + DEFAULT_DIR); + } + return instance; + } + public void addDestination(String destName) { ActiveMQDestination dest = @@ -52,14 +59,33 @@ public void addDestination(String destName) public void startup() { + /* Find remote broker if we're not running on the reporting machine + */ + String remoteBrokerUrl = null; + Component reportingComponent = Components.lookup(Reporting.class); + if (null!=reportingComponent && !reportingComponent.isLocal()) { + log.info("Searching for remote reporting broker"); + NavigableSet services = reportingComponent.getServices(); + for (Service service: services) { + remoteBrokerUrl = String.format(DEFAULT_REMOTE_URL_FORMAT, + service.getHost(), DEFAULT_PORT); + } + } else { + log.info("Reporting broker will run locally"); + remoteBrokerUrl = null; + } + + /* Startup BrokerService in separate thread and provide url and remoteUrl + */ try { brokerService = new BrokerService(); brokerService.setBrokerName(brokerName); brokerService.setDataDirectory(brokerDataDir); brokerService.addConnector(brokerUrl); - ActiveMQDestination[] dests = new ActiveMQDestination[destinations.size()]; - destinations.toArray(dests); - brokerService.setDestinations(dests); + if (remoteBrokerUrl != null) { + brokerService.addNetworkConnector(remoteBrokerUrl); + } + brokerService.setUseJmx(false); brokerThread = new JmsBrokerThread(brokerService); brokerThread.start(); Thread.sleep(1000); // give the broker a moment to startup; TODO: @@ -96,7 +122,12 @@ public String getBrokerUrl() public static void main(String[] args) throws Exception { - QueueBroker broker = new QueueBroker(DEFAULT_NAME, DEFAULT_DIR, DEFAULT_URL); + String remoteBrokerUrl = null; + if (args.length > 0) { + remoteBrokerUrl = args[0]; + } + QueueBroker broker = new QueueBroker(DEFAULT_NAME, DEFAULT_URL, + DEFAULT_DIR); broker.startup(); } diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageDisplayBean.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageDisplayBean.java index 743869ef1e2..122a6c340bd 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageDisplayBean.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageDisplayBean.java @@ -69,5 +69,10 @@ public Long getObjectsSizeTime() INTERNAL_UNITS.getSizeTimeSizeUnit(), units.getSizeTimeSizeUnit(), INTERNAL_UNITS.getSizeTimeTimeUnit(), units.getSizeTimeTimeUnit()); } + + public Units getUnits() + { + return units; + } } diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageDisplayDb.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageDisplayDb.java index 828403b0045..cbe479daf22 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageDisplayDb.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageDisplayDb.java @@ -15,7 +15,7 @@ private StorageDisplayDb(StorageUsageLog usageLog) } private static StorageDisplayDb instance = null; - + public static StorageDisplayDb getInstance() { if (instance == null) { @@ -23,7 +23,7 @@ public static StorageDisplayDb getInstance() } return instance; } - + public List search(Period period, GroupByCriterion criterion, Units displayUnits) { @@ -37,7 +37,7 @@ public List search(Period period, GroupByCriterion criterion } return items; } - + public List searchGroupBy( Period period, GroupByCriterion groupByCrit, GroupByCriterion crit, Units displayUnits) diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageEventPoller.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageEventPoller.java index bb17d18c3a6..bdec8231f88 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageEventPoller.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageEventPoller.java @@ -10,6 +10,12 @@ import com.eucalyptus.reporting.event.*; import com.eucalyptus.reporting.queue.QueueReceiver; +/** + *

StorageEventPoller is run periodically and polls the message queue for + * new storage events. It then aggregates those events into snapshots. + * + * @author tom.werges + */ public class StorageEventPoller { private static Logger LOG = Logger.getLogger( StorageEventPoller.class ); @@ -26,6 +32,8 @@ public StorageEventPoller(QueueReceiver receiver) public void writeEvents() { + LOG.info("Queue poll:" + System.currentTimeMillis()); + EntityWrapper entityWrapper = EntityWrapper.get( StorageUsageSnapshot.class ); try { @@ -56,6 +64,7 @@ public void writeEvents() event = receiver.receiveEventNoWait()) { StorageEvent storageEvent = (StorageEvent) event; + LOG.info("Receive event:" + storageEvent.toString()); UsageDataKey key = new UsageDataKey(storageEvent.getOwnerId(), storageEvent.getAccountId(), storageEvent.getClusterName(), diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageLog.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageLog.java index 36d18723442..e5109650a68 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageLog.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageLog.java @@ -11,7 +11,7 @@ import com.eucalyptus.reporting.instance.InstanceAttributes; /** - *

StorageUsageLog + *

StorageUsageLog is the main API for accessing storage usage information. * * @author tom.werges */ @@ -232,6 +232,7 @@ public Map> scanSummarize( SummaryInfo info = innerMap.get(innerCritVal); StorageUsageData lastData = info.getLastData(); long durationSecs = (timestampMs - info.getLastTimestamp()) / 1000; + System.out.println("info:" + info + " summary:" + info.getSummary() + " lastData:" + lastData); info.getSummary().updateValues(lastData.getVolumesMegs(), lastData.getSnapshotsMegs(), lastData.getObjectsMegs(), durationSecs); diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageSnapshot.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageSnapshot.java index 7464c645474..02d18d7d1ab 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageSnapshot.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageSnapshot.java @@ -6,7 +6,7 @@ *

StorageUsageSnapshot is a snapshot of disk data usage at some point in * time. * - * @author twerges + * @author tom.werges */ @Entity @PersistenceContext(name="reporting") @@ -22,7 +22,7 @@ protected StorageUsageSnapshot() { } - + public StorageUsageSnapshot(SnapshotKey key, StorageUsageData usageData) { this.key = key; @@ -43,4 +43,5 @@ public String toString() { return String.format("[key:%s,usageData:%s]", this.key, this.usageData); } + } diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageSummary.java b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageSummary.java index 3abd013e5d6..a0473634db3 100644 --- a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageSummary.java +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/StorageUsageSummary.java @@ -6,7 +6,7 @@ * usage. * *

StorageUsageSummary is not a bean. StorageUsageSummary accumulates - * data through the

update
method and then returns results of + * data through the
update
method and then returns resulting * statistics using the various
get
methods. * * @author tom.werges diff --git a/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/package.html b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/package.html new file mode 100644 index 00000000000..90105d2c7ab --- /dev/null +++ b/clc/modules/reporting/src/main/java/com/eucalyptus/reporting/storage/package.html @@ -0,0 +1,33 @@ + +

The reporting.storage package contains classes for the storage and retrieval +of historical usage information for Walrus/S3. It could be used to generate +timely visual reports, of S3/Walrus usage over some past time period (like a +month), in order to monitor usage trends or to conduct billing. + +

The reporting.storage package stores its accounting information as a series +of snapshots, each of which contains the total resource usage for +a given (owner,account,cluster,availability_zone) combination over some time +period. + +

The reporting.storage package receives events from S3/Walrus indicating + allocation and deallocation of Walrus/S3 objects. Then the reporting.storage +package uses those events to generate snapshots, every n seconds, of +total resource utilization for each (owner,account,cluster,zone) combination. + +

Events are transmitted to the reporting.storage package over a reliable +message queue. Events are transmitted using the reporting.queue package. + +

Reporting data stored by the reporting.storage package can be accessed +using the

StorageUsageLog
class. This class will allow you to scan +through the usage logs and gather usage information. This is the main class +for accessing reporting.storage information. + +

In addition, there is a

StorageDisplayDb
class which is built +atop the
StorageUsageLog
class. The
StorageDisplayDb
+class adds logic for displayable Strings, unit conversions, and so on. It +emits displayable bean classes which can be used by jasper or other report +generation engines. + +

The reporting.storage package is used by

Reports
class in the +
www
module, which generates visual reports based on user +selections. diff --git a/clc/modules/reporting/src/test/java/com/eucalyptus/reporting/instance/FalseDataGenerator.java b/clc/modules/reporting/src/test/java/com/eucalyptus/reporting/instance/FalseDataGenerator.java index 5da01476996..92caefd4439 100644 --- a/clc/modules/reporting/src/test/java/com/eucalyptus/reporting/instance/FalseDataGenerator.java +++ b/clc/modules/reporting/src/test/java/com/eucalyptus/reporting/instance/FalseDataGenerator.java @@ -2,8 +2,10 @@ import java.util.*; +import com.eucalyptus.reporting.ReportingBootstrapper; import com.eucalyptus.reporting.GroupByCriterion; import com.eucalyptus.reporting.Period; +import com.eucalyptus.reporting.event.Event; import com.eucalyptus.reporting.event.InstanceEvent; import com.eucalyptus.reporting.queue.QueueBroker; import com.eucalyptus.reporting.queue.QueueFactory; @@ -12,13 +14,13 @@ import com.eucalyptus.upgrade.TestDescription; /** - *

FalseDataGenerator generates false data about instances. - * It generates fake starting and ending times, imaginary resource - * usage, fictitious clusters, and non-existent accounts and users. + *

FalseDataGenerator generates false data about instances. It generates + * fake starting and ending times, imaginary resource usage, fictitious + * clusters, and non-existent accounts and users. * - *

The main use of this class is to be called from the - *

clc/tools/runTest.sh
tool, specifying the class name and a - * method below. + *

FalseDataGenerator is meant to be called from the command-line tool, + *

clc/tools/runTest.sh
, specifying the class name and a method + * below. * *

False data should be deleted afterward by calling the *

deleteFalseData
method. @@ -40,24 +42,31 @@ public class FalseDataGenerator private static final int NUM_ACCOUNT = 16; private static final int NUM_CLUSTER = 4; private static final int NUM_AVAIL_ZONE = 2; + + private static ReportingBootstrapper reportingBootstrapper = null; private enum FalseInstanceType { M1SMALL, C1MEDIUM, M1LARGE, M1XLARGE, C1XLARGE; } - /** - * @param remote Must equal "local" if this is to be run locally; any other - * value means it will run over the MQ and will search for a broker. - */ - public static void generateFalseData(String remote) + public static void generateFalseData() { - boolean isLocal = (remote != null && remote.equalsIgnoreCase("local")); - System.out.println(" ----> GENERATING FALSE DATA " + (isLocal ? "(local)" : "(remote)")); - + System.out.println(" ----> GENERATING FALSE DATA"); + + TestEventListener listener = new TestEventListener(); + listener.setCurrentTimeMillis(START_TIME); + + reportingBootstrapper = new ReportingBootstrapper(); + reportingBootstrapper.setOverriddenInstanceEventListener(listener); + reportingBootstrapper.start(); + + QueueSender queueSender = QueueFactory.getInstance().getSender(QueueIdentifier.INSTANCE); + + List fakeInstances = new ArrayList(); - + for (int i = 0; i < NUM_INSTANCE; i++) { String uuid = new Long(i).toString(); @@ -74,16 +83,9 @@ public static void generateFalseData(String remote) availZone); fakeInstances.add(insAttrs); } - QueueSender queueSender = null; - TestEventListener listener = null; - if (isLocal) { - listener = new TestEventListener(); - listener.setCurrentTimeMillis(START_TIME); - } else { - queueSender = QueueFactory.getInstance().getSender(QueueIdentifier.INSTANCE); - } + for (int i=0; i el) { // empty } @Override - public void removeEventListener(EventListener el) + public void removeEventListener(EventListener el) { // empty } diff --git a/clc/modules/storage-controller/build.xml b/clc/modules/storage-controller/build.xml index e9b1e1f951b..3870bb5ad85 100644 --- a/clc/modules/storage-controller/build.xml +++ b/clc/modules/storage-controller/build.xml @@ -67,6 +67,9 @@ + + + diff --git a/clc/modules/www/build.xml b/clc/modules/www/build.xml index e4cbf81b7ec..19a68b3c569 100644 --- a/clc/modules/www/build.xml +++ b/clc/modules/www/build.xml @@ -72,6 +72,9 @@ + + + diff --git a/clc/tools/runTest.sh b/clc/tools/runTest.sh index 8327479cb99..f783f074dbe 100755 --- a/clc/tools/runTest.sh +++ b/clc/tools/runTest.sh @@ -29,9 +29,9 @@ FILES=$(\ls -1 ${EUCALYPTUS}/usr/share/eucalyptus/*.jar) for FILE in $FILES; do export CLASSPATH=${FILE}:${CLASSPATH} done -CLASSPATH=${EUCALYPTUS}/etc/eucalyptus/cloud.d/upgrade:${EUCALYPTUS}/etc/eucalyptus/cloud.d/scripts:${CLASSPATH} - -java -Xbootclasspath/p:${EUCALYPTUS}/usr/share/eucalyptus/openjdk-crypto.jar -classpath ${CLASSPATH} \ +CLuSSPATH=${EUCALYPTUS}/etc/eucalyptus/cloud.d/upgrade:${EUCALYPTUS}/etc/eucalyptus/cloud.d/scripts:${CLASSPATH} +echo -e "${CLASSPATH//:/\n}" +java -Xms1g -Xmx3g -XX:MaxPermSize=768m -Xbootclasspath/p:${EUCALYPTUS}/usr/share/eucalyptus/openjdk-crypto.jar -classpath ${CLASSPATH} \ -Deuca.home=${EUCALYPTUS} \ -Deuca.lib.dir=${EUCALYPTUS} \ -Deuca.upgrade.new.dir=${EUCALYPTUS} \