2 * Copyright 2011-2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and
31 * documentation are those of the authors and should not be
32 * interpreted as representing official policies, either expressed
33 * or implied, of GRNET S.A.
36 package gr.grnet.aquarium.util
40 import gr.grnet.aquarium.event.ResourceEvent
41 import scopt.OptionParser
42 import gr.grnet.aquarium.messaging.AkkaAMQP
43 import java.lang.StringBuffer
44 import gr.grnet.aquarium.logic.accounting.Policy
45 import gr.grnet.aquarium.store.memory.MemIMEvent
46 import gr.grnet.aquarium.event.im.{StdIMEvent, IMEventModel}
49 * Generates random resource events to use as input for testing and
50 * injects them to the specified exchange.
52 * @author Georgios Gousios <gousiosg@gmail.com>
54 trait RandomEventGenerator extends AkkaAMQP {
56 val userIds = 1 to 1000
57 val clientIds = 1 to 4
59 val resources = Policy.policy.resources.map{r => r.name}
60 val tsFrom = 1293840000000L //1/1/2011 0:00:00 GMT
61 val tsTo = 1325376000000L //1/1/2012 0:00:00 GMT
62 val eventVersion = 1 to 4
64 private val seed = 0xdeadbeef
65 private lazy val rnd = new Random(seed)
68 * Generate a random resource event
70 def nextUserEvent(): IMEventModel = {
71 val ts = tsFrom + (scala.math.random * ((tsTo - tsFrom) + 1)).asInstanceOf[Long]
74 id = CryptoUtils.sha1(genRndAsciiString(35)),
75 occurredMillis = ts.toLong,
76 receivedMillis = ts.toLong,
77 userID = userIds(rnd.nextInt(100)).toString,
78 clientID = "defclient",
79 isActive = rnd.nextBoolean,
80 role = Array("PROF", "STUDENT", "ADMIN").apply(rnd.nextInt(3)),
81 eventVersion = 1.toString,
82 eventType = Array("ACTIVE", "SUSPENDED").apply(rnd.nextInt(2)),
88 * Generate a random resource event
90 def genPublishUserEvents(num: Int) = {
91 val publisher = producer(im_exchanges(0))
95 var event = nextUserEvent()
96 publisher ! Message(event.toJsonString.getBytes, "astakos.user")
101 * Generete and publish create events for test users
103 def initUsers(num: Int) = {
104 val publisher = producer(im_exchanges(0))
106 userIds.filter(_ < num).foreach {
108 val ts = tsFrom + (scala.math.random * ((tsTo - tsFrom) + 1)).asInstanceOf[Long]
109 val user = new StdIMEvent(
110 id = CryptoUtils.sha1(genRndAsciiString(35)),
111 occurredMillis = ts.toLong,
112 receivedMillis = ts.toLong,
114 clientID = "defclient",
115 isActive = rnd.nextBoolean,
116 role = Array("PROF", "STUDENT", "ADMIN").apply(rnd.nextInt(3)),
117 eventVersion = 1.toString,
118 eventType = "CREATE",
121 publisher ! Message(user.toJsonString.getBytes, "astakos.user")
126 * Get the next random resource event
128 def nextResourceEvent() : ResourceEvent = {
129 val res = rnd.shuffle(resources).head
131 val extra = res match {
132 case "vmtime" => Map("vmid" -> rnd.nextInt(vmIds.max).toString)
133 case _ => Map[String, String]()
136 val value = res match {
137 case "vmtime" => rnd.nextInt(1)
138 case _ => rnd.nextInt(5000)
141 val ts = tsFrom + (scala.math.random * ((tsTo - tsFrom) + 1)).asInstanceOf[Long]
142 val str = genRndAsciiString(35)
145 CryptoUtils.sha1(str),
147 rnd.nextInt(userIds.max).toString,
148 rnd.nextInt(clientIds.max).toString,
149 res, "1", 1.toString, value, extra)
152 def genRndAsciiString(size: Int): String = {
154 i => rnd.nextPrintableChar()
155 }.foldLeft(new StringBuffer()){
156 (a, b) => a.append(b)
161 * Generate resource events and publish them to the queue
163 def genPublishResEvents(num: Int) = {
166 val publisher = producer(resevent_exchanges(0))
170 var event = nextResourceEvent
171 publisher ! Message(event.toBytes,
172 "%s.%s.%s".format("",event.clientID, event.resource))
177 object RandomEventGen extends RandomEventGenerator {
179 case class Config(var i: Boolean = false,
180 var u: Boolean = false,
181 var r: Boolean = false,
182 var nummsg: Int = 100)
184 val config = new Config
186 private val parser = new OptionParser("RandomEventGen") {
187 opt("i", "im-events", "Generate IM events", {config.i = true})
188 opt("u", "user-create", "Generate IM events that create users", {config.u = true})
189 opt("r", "resource-events", "Generate resource events", {config.r = true})
190 arg("nummsgs", "Number of msgs to generate", {num: String => config.nummsg = Integer.parseInt(num)})
193 def main(args: Array[String]): Unit = {
195 if (!parser.parse(args))
198 if (!config.i && !config.u && !config.r) {
199 println("One of -i, -u, -r must be specified")
203 println("Publishing %d msgs, hit Ctrl+c to stop".format(config.nummsg))
204 if (config.r) genPublishResEvents(config.nummsg)
205 if (config.u) initUsers(config.nummsg)
206 if (config.i) genPublishUserEvents(config.nummsg)
209 private def errexit() = {