Preparing the move to master
[aquarium] / src / test / scala / gr / grnet / aquarium / user / UserStateComputationsTest.scala
1 package gr.grnet.aquarium.user
2
3 import org.junit.Test
4 import gr.grnet.aquarium.Configurator
5 import gr.grnet.aquarium.store.memory.MemStore
6 import gr.grnet.aquarium.util.date.MutableDateCalc
7 import gr.grnet.aquarium.logic.accounting.dsl._
8 import java.util.Date
9 import simulation.{ConcurrentVMLocalUIDGenerator, ClientServiceSim, UserSim}
10 import gr.grnet.aquarium.logic.accounting.{Policy, Accounting}
11 import gr.grnet.aquarium.util.{Loggable, ContextualLogger}
12 import com.ckkloverdos.maybe.{Just, NoVal}
13
14
15 /**
16  *
17  * @author Christos KK Loverdos <loverdos@gmail.com>
18  */
19 class UserStateComputationsTest extends Loggable {
20   val PolicyYAML = """
21 aquariumpolicy:
22   resources:
23     - resource:
24       name: bandwidth
25       unit: MB/hr
26       complex: false
27       costpolicy: discrete
28     - resource:
29       name: vmtime
30       unit: Hour
31       complex: true
32       costpolicy: onoff
33       descriminatorfield: vmid
34     - resource:
35       name: diskspace
36       unit: MB/hr
37       complex: false
38       costpolicy: continuous
39
40   implicitvars:
41     - price
42     - volume
43
44   algorithms:
45     - algorithm:
46       name: default
47       bandwidth: $NotNow
48       vmtime: $NotNow
49       diskspace: $NotNow
50       effective:
51         from: 0
52
53   pricelists:
54     - pricelist:
55       name: default
56       bandwidth: 1.0
57       vmtime: 1.0
58       diskspace: 1.0
59       effective:
60         from: 0
61
62   creditplans:
63     - creditplan:
64       name: default
65       credits: 100
66       at: "00 00 1 * *"
67       effective:
68         from: 0
69
70   agreements:
71     - agreement:
72       name: default
73       algorithm: default
74       pricelist: default
75       creditplan: default
76   """
77
78   val DefaultPolicy = new DSL{}.parse(PolicyYAML)
79
80   // TODO: integrate this with the rest of the simulation stuff
81   // TODO: since, right now, the resource strings have to be given twice
82   val VMTimeResource    = DSLComplexResource("vmtime",    "Hr",    OnOffCostPolicy,      "")
83   val DiskspaceResource = DSLComplexResource("diskspace", "MB/Hr", ContinuousCostPolicy, "")
84   val BandwidthResource = DSLComplexResource("bandwidth", "MB/Hr", DiscreteCostPolicy,   "")
85   val DefaultResourcesMap = new DSLResourcesMap(VMTimeResource :: DiskspaceResource :: BandwidthResource :: Nil)
86
87   // There are two client services, synnefo and pithos.
88   val TheUIDGenerator = new ConcurrentVMLocalUIDGenerator
89   val Synnefo = ClientServiceSim("synnefo")(TheUIDGenerator)
90   val Pithos  = ClientServiceSim("pithos")(TheUIDGenerator)
91
92   @Test
93   def testOne: Unit = {
94     val clog = ContextualLogger.fromOther(NoVal, logger, "testOne()")
95     val StartOfBillingYearDateCalc = new MutableDateCalc(2012, 1, 1)
96 //    println("StartOfBillingYearDateCalc = %s".format(StartOfBillingYearDateCalc))
97     val UserCreationDateCalc = StartOfBillingYearDateCalc.copy.goMinusMonths(2)
98 //    println("UserCreationDateCalc = %s".format(UserCreationDateCalc))
99
100     val computer = new UserStateComputations
101
102     val mc = Configurator.MasterConfigurator.withStoreProviderClass(classOf[MemStore])
103     Policy.withConfigurator(mc)
104
105     val storeProvider = mc.storeProvider
106     val userStateStore = storeProvider.userStateStore
107     val resourceEventStore = storeProvider.resourceEventStore
108     val policyStore = storeProvider.policyStore
109
110     val policyOccurredMillis  = StartOfBillingYearDateCalc.toMillis
111     val policyValidFromMillis = StartOfBillingYearDateCalc.copy.goPreviousYear.toMillis
112     val policyValidToMillis   = StartOfBillingYearDateCalc.copy.goNextYear.toMillis
113     policyStore.storePolicyEntry(DefaultPolicy.toPolicyEntry(policyOccurredMillis, policyValidFromMillis, policyValidToMillis))
114
115     // A new user is created on 2012-01-15 00:00:00.000
116     val UserCKKL  = UserSim("CKKL", UserCreationDateCalc.toDate, storeProvider.resourceEventStore)
117
118     // By convention
119     // - synnefo is for VMTime and Bandwidth
120     // - pithos is for Diskspace
121     val VMTimeInstance    = Synnefo.newVMTime   (UserCKKL, "VM.1")
122     val BandwidthInstance = Synnefo.newBandwidth(UserCKKL, "3G.1")
123     val DiskInstance      = Pithos .newDiskspace(UserCKKL, "DISK.1")
124
125     // Let's create our dates of interest
126     val vmStartDateCalc = StartOfBillingYearDateCalc.copy.goPlusDays(1).goPlusHours(1)
127 //    println("vmStartDateCalc = %s".format(vmStartDateCalc))
128     // 2012-01-16 01:00:00.000
129     val vmStartDate = vmStartDateCalc.toDate
130
131     // Within January, create one VM ON-OFF ...
132     val onOff1_M = VMTimeInstance.newONOFF(vmStartDate, 9)
133
134     val diskConsumptionDateCalc = StartOfBillingYearDateCalc.copy.goPlusHours(3)
135     // 2012-01-16 04:00:00.000
136     val diskConsumptionDate1 = diskConsumptionDateCalc.toDate
137     // 2012-01-17 05:00:00.000
138     val diskConsumptionDateCalc2 = diskConsumptionDateCalc.copy.goPlusDays(1).goPlusHours(1)
139     val diskConsumptionDate2 = diskConsumptionDateCalc2.toDate
140
141     // ... and two diskspace changes
142     val consume1_M = DiskInstance.consumeMB(diskConsumptionDate1, 99)
143     val consume2_M = DiskInstance.consumeMB(diskConsumptionDate2, 23)
144
145     // 100MB 3G bandwidth
146     val bwDateCalc = diskConsumptionDateCalc2.copy.goPlusDays(1)
147     BandwidthInstance.useBandwidth(bwDateCalc.toDate, 100.0)
148
149     // ... and one "future" event
150     // 2012-02-07 07:07:07.007
151     DiskInstance.consumeMB(
152       StartOfBillingYearDateCalc.copy.
153         goNextMonth.goPlusDays(6).
154         goPlusHours(7).
155         goPlusMinutes(7).
156         goPlusSeconds(7).
157         goPlusMillis(7).toDate,
158       777)
159
160     clog.debug("")
161     clog.debug("=== Events by OccurredMillis ===")
162     clog.withIndent {
163       for(event <- UserCKKL.myResourceEventsByOccurredDate) {
164         clog.debug(event.toDebugString(DefaultResourcesMap))
165       }
166     }
167     clog.debug("=== Events by OccurredMillis ===")
168     clog.debug("")
169
170     val billingMonthInfo = BillingMonthInfo.fromDateCalc(StartOfBillingYearDateCalc)
171
172     val initialUserState = computer.createFirstUserState(
173       userId = UserCKKL.userId,
174       millis = StartOfBillingYearDateCalc.copy.goPreviousYear.toMillis
175     )
176
177     val userStateM = computer.doFullMonthlyBilling(
178       UserCKKL.userId,
179       billingMonthInfo,
180       userStateStore,
181       resourceEventStore,
182       policyStore,
183       UserCKKL.userCreationDate.getTime,
184       initialUserState,
185       initialUserState,
186       DefaultPolicy,
187       DefaultResourcesMap,
188       new Accounting{},
189       Just(clog)
190     )
191     
192     clog.debug("userStateM = %s".format(userStateM))
193     userStateM.forFailed { failed ⇒
194       clog.error(failed)
195       failed.exception.printStackTrace()
196       NoVal
197     }
198   }
199 }