package gr.grnet.aquarium.logic
+import events.{EventProcessor, Event}
import gr.grnet.aquarium.model._
-import collection.JavaConversions._
-import collection.immutable.HashSet
-import collection.mutable.Buffer
-import java.util.Date
trait Bills {
+ def calcBills() = {
+ val entities = DB.findAll[Entity]("select e from Entity e")
+ //entities.foreach{x => calcBills(x)}
+ }
+ def calcBills(e: Entity) = {
+ EventProcessor.process(eventsFromDB(e))(f => true)
+ }
+
+ def eventsFromDB(e: Entity) : List[Event] = {
+ val events = List()
+ events
+ }
}
\ No newline at end of file
package gr.grnet.aquarium.logic.accounting
import agreements.AgreementRegistry
-import java.util.Date
import gr.grnet.aquarium.model.{Entity, DB}
+import policies.DefaultRatePolicy
+import java.util.Date
+
-class AccountingEvent(et: AccountingEventType.Value, when: Date,
- who: Long, amount: Float, rel: List[Long]) {
+/** An accounting event represents any event that the accounting system
+ * must process.
+ */
+class AccountingEvent(et: AccountingEventType.Value, start: Date,
+ end: Date, who: Long, amount: Float, rel: List[Long]) {
- def date() = when
+ def dateStart() = start
+ def dateEnd() = end
def entity() = DB.find(classOf[Entity], who) match {
case Some(x) => x
def kind() = et
- def process() = policy().process(this)
+ def process() = {
+ val evts = policy().map{p => p.process(this)}
+ val total = evts.map(x => x.amount).foldLeft(0F)((a, sum) => a + sum)
+ new AccountingEntry(rel, new Date(), total, evts.head.entryType)
+ }
- def policy(): Policy = {
+ def policy(): List[Policy] = {
val agr = AgreementRegistry.getAgreement(entity().agreement) match {
case Some(x) => x
case None => throw new Exception("No agreement with id:" +
entity().agreement)
}
- agr.policy(et, when) match {
+ /*agr.policy(et, when) match {
case Some(x) => x
case None => throw new Exception("No charging policy for event type:" +
et + " in period starting from:" + when.getTime)
- }
+ }*/
+ List()
}
def getRate(): Float = {
package gr.grnet.aquarium.logic.accounting
+import java.util.Date
+
abstract class Policy(et: AccountingEntryType.Value) {
private def makeEntry(event: AccountingEvent, amount: Float) : AccountingEntry = {
- new AccountingEntry(event.relatedEvents(),event.date(), amount, et)
+ new AccountingEntry(event.relatedEvents(), new Date(), amount, et)
}
def process(evt: AccountingEvent) = {
object EventProcessor {
- def process(from: Option[Date], to: Option[Date],
- events: (Option[Date], Option[Date]) => List[Event]): List[AccountingEvent] = {
- val evts = events(from, to)
+ def process(events: List[Event])
+ (evtFilter: (Event) => Boolean): List[AccountingEvent] = {
- val dummy = new AccountingEvent(AccountingEventType.VMTime, new Date() , 0, 0, List())
+ val evts = events.filter(evtFilter)
+ val dummy = new AccountingEvent(AccountingEventType.VMTime, new Date(), new Date(), 0, 0, List())
- evts.map {f => f.who}.distinct.map {
- //Events are calculated per user
- u =>
- //Time sorted list of events for user
- val userEvents = evts.filter(_.who == u).sortBy(_.when)
- userEvents.map {
- e => e match {
- case v: VMStarted => //Find stop event and calculate time usage
- val stop = findVMStopEvent(userEvents, v)
- val time = stop match {
- case Some(x) => x.when
- case None => to.getOrElse(new Date()) //Now
- }
- val stopid = stop match {
- case Some(x) => x.id
- case None => -1 //Now
- }
- val totaltime = time.getTime - v.w.getTime
- assert(totaltime > 0)
- new AccountingEvent(AccountingEventType.VMTime, e.when(),
- u, totaltime,
- List(v.id, stopid))
- // case v : VMStarted =>None
- // case v : VMStopped =>None
- case v: DiskSpaceChanged =>
- assert(v.bytes > 0)
- new AccountingEvent(AccountingEventType.DiskSpace,
- e.when(), u, v.bytes, List(v.id()))
- case v: DataUploaded =>
- assert(v.bytes > 0)
- new AccountingEvent(AccountingEventType.NetDataUp, e.when, u,
- v.bytes, List(v.id()))
- case v: DataDownloaded =>
- assert(v.bytes > 0)
- new AccountingEvent(AccountingEventType.NetDataDown, e.when, u,
- v.bytes, List(v.id()))
- // case v : SSaasVMCreated => None
- // case v : SSaasVMStarted =>None
- // case v : SSaasVMStopped =>None
- case _ => dummy
- }
+ evts.sortBy(_.when).map {
+ e =>
+ val u = e.who()
+ e match {
+ case v: VMStarted => //Find stop event and calculate time usage
+ val stop = findVMStopEvent(evts, v)
+ val time = stop match {
+ case Some(x) => x.when
+ case None => new Date() //Now
+ }
+ val stopid = stop match {
+ case Some(x) => x.id
+ case None => -1
+ }
+ val totaltime = time.getTime - v.w.getTime
+ assert(totaltime > 0)
+ new AccountingEvent(AccountingEventType.VMTime, e.when, time, u, totaltime, List(v.id, stopid))
+ // case v : VMStarted =>None
+ // case v : VMStopped =>None
+ case v: DiskSpaceChanged =>
+ assert(v.bytes > 0)
+ new AccountingEvent(AccountingEventType.DiskSpace, e.when, e.when, u, v.bytes, List(v.id()))
+ case v: DataUploaded =>
+ assert(v.bytes > 0)
+ new AccountingEvent(AccountingEventType.NetDataUp, e.when, e.when, u, v.bytes, List(v.id()))
+ case v: DataDownloaded =>
+ assert(v.bytes > 0)
+ new AccountingEvent(AccountingEventType.NetDataDown, e.when, e.when, u, v.bytes, List(v.id()))
+ // case v : SSaasVMCreated => None
+ // case v : SSaasVMStarted =>None
+ // case v : SSaasVMStopped =>None
+ case _ => dummy
}
- }.flatten.filter(p => p != dummy) //Remove dummy events
+ }.filter(p => p != dummy) //Remove dummy events
}
/**Find a the first corresponding VM stop event in a list of messages*/
import gr.grnet.aquarium.logic.Bills
import gr.grnet.aquarium.model.{User, DB}
import gr.grnet.aquarium.logic.accounting.policies.DefaultRatePolicy
-import java.util.Date
import gr.grnet.aquarium.logic.accounting.{Agreement, AccountingEvent, AccountingEntryType, AccountingEventType}
import gr.grnet.aquarium.logic.accounting.agreements.AgreementRegistry
+import java.util.Date
class BillingTest
extends FixtureLoader with Bills {
DB.persistAndFlush(u)
- val evt = new AccountingEvent(AccountingEventType.VMTime,
- new Date(4), u.id, 15, List())
- val entry = evt.process()
-
+ // Try with a basic event
+ var evt = new AccountingEvent(AccountingEventType.VMTime,
+ new Date(4), new Date(10), u.id, 15, List())
+ var entry = evt.process()
assertEquals(entry.amount, 15 * 0.001F, 0.00001)
+
+ // Try with another event type
+ evt = new AccountingEvent(AccountingEventType.DiskSpace,
+ new Date(4), new Date(4), u.id, 12.3F, List())
+ entry = evt.process()
+ assertEquals(entry.amount, 12.3F * 0.00002F, 0.00001)
}
@After
class EventProcessorTest {
- def getEvents(from: Option[Date], to: Option[Date]): List[Event] = {
+ def getEvents(): List[Event] = {
//Tmp list of events
List[Event](
new VMCreated(1, new Date(123), 2, 1),
@Test
def testProcess() = {
- var result = EventProcessor.process(None, None, getEvents)
+ val result = EventProcessor.process(getEvents)(f => true)
assert(result.size == 6)
}
}
\ No newline at end of file