Statistics
| Branch: | Tag: | Revision:

root / src / main / scala / gr / grnet / aquarium / util / RandomEventGenerator.scala @ 4dfd9ec3

History | View | Annotate | Download (6.2 kB)

1
/*
2
 * Copyright 2011 GRNET S.A. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 *   1. Redistributions of source code must retain the above
9
 *      copyright notice, this list of conditions and the following
10
 *      disclaimer.
11
 *
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.
16
 *
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.
29
 *
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.
34
 */
35

    
36
package gr.grnet.aquarium.util
37

    
38
import akka.amqp._
39
import util.Random
40
import gr.grnet.aquarium.logic.events.{UserEvent, ResourceEvent}
41
import scopt.OptionParser
42
import gr.grnet.aquarium.messaging.{MessagingNames, AkkaAMQP}
43
import java.lang.StringBuffer
44

    
45
/**
46
 *  Generates random resource events to use as input for testing and
47
 *  injects them to the specified exchange.
48
 *
49
 * @author Georgios Gousios <gousiosg@gmail.com>
50
 */
51
trait RandomEventGenerator extends AkkaAMQP {
52

    
53
  val userIds = 1 to 100
54
  val clientIds = 1 to 4
55
  val vmIds = 1 to 4000
56
  val resources = List("vmtime", "bndup", "bnddown", "dsksp")
57
  val tsFrom = 1293840000000L //1/1/2011 0:00:00 GMT
58
  val tsTo = 1325376000000L   //1/1/2012 0:00:00 GMT
59
  val eventVersion = 1 to 4
60

    
61
  private val seed = 0xdeadbeef
62
  private lazy val rnd = new Random(seed)
63

    
64
  /**
65
   * Generate a random resource event
66
   */
67
  def nextUserEvent(): UserEvent = {
68

    
69
    val sha1 = CryptoUtils.sha1(genRndAsciiString(35))
70
    val ts = tsFrom + (scala.math.random * ((tsTo - tsFrom) + 1)).asInstanceOf[Long]
71
    val id = userIds.apply(rnd.nextInt(100))
72
    val event = Array("ACTIVE", "SUSPENDED").apply(rnd.nextInt(2))
73
    val idp = Array("LOCAL", "SHIBBOLETH", "OPENID").apply(rnd.nextInt(3))
74
    val tenant = Array("TENTANT1", "TENANT2").apply(rnd.nextInt(2))
75
    val role = Array("ADMIN", "NORMAL").apply(rnd.nextInt(2))
76

    
77
    UserEvent(sha1, ts.toLong, ts.toLong, id.toString, 1, 2, event, idp, tenant, Array(role))
78
  }
79

    
80
  /**
81
   * Generate a random resource event
82
   */
83
  def genPublishUserEvents(num: Int) = {
84
    val publisher = producer(MessagingNames.IM_EXCHANGE)
85

    
86
    (1 to num).foreach {
87
      n =>
88
        var event = nextUserEvent()
89
        publisher ! Message(event.toBytes, "")
90
    }
91
  }
92

    
93
  /**
94
   * Generete and publish create events for test users
95
   */
96
  def initUsers = {
97
    val publisher = producer(MessagingNames.IM_EXCHANGE)
98

    
99
    userIds.foreach {
100
      i =>
101
        val sha1 = CryptoUtils.sha1(genRndAsciiString(35))
102
        val ts = tsFrom + (scala.math.random * ((tsTo - tsFrom) + 1)).asInstanceOf[Long]
103
        val user = UserEvent(sha1, ts, ts, i.toString, 1, 1, "ACTIVE", "LOCAL", "TENTANT1", Array("NORMAL"))
104
        publisher ! Message(user.toBytes, "%s.%s".format(MessagingNames.IM_EVENT_KEY,"CREATED"))
105
    }
106
  }
107

    
108
  /**
109
   * Get the next random resource event
110
   */
111
  def nextResourceEvent() : ResourceEvent = {
112
    val res = rnd.shuffle(resources).head
113

    
114
    val extra = res match {
115
      case "vmtime" => Map("vmid" -> rnd.nextInt(vmIds.max).toString)
116
      case _ => Map[String, String]()
117
    }
118

    
119
    val value = res match {
120
      case "vmtime" => rnd.nextInt(1)
121
      case _ => rnd.nextInt(5000)
122
    }
123

    
124
    val ts = tsFrom + (scala.math.random * ((tsTo - tsFrom) + 1)).asInstanceOf[Long]
125
    val str = genRndAsciiString(35)
126

    
127
    ResourceEvent(
128
      CryptoUtils.sha1(str),
129
      ts, ts,
130
      rnd.nextInt(userIds.max).toString,
131
      rnd.nextInt(clientIds.max).toString,
132
      res, 1.toString, value, extra)
133
  }
134

    
135
  def genRndAsciiString(size: Int): String = {
136
    (1 to size).map{
137
      i => rnd.nextPrintableChar()
138
    }.foldLeft(new StringBuffer()){
139
      (a, b) => a.append(b)
140
    }.toString
141
  }
142

    
143
  /**
144
   * Generate resource events and publish them to the queue
145
   */
146
  def genPublishResEvents(num: Int) = {
147

    
148
    assert(num > 0)
149
    val publisher = producer(MessagingNames.AQUARIUM_EXCHANGE)
150

    
151
    (1 to num).foreach {
152
      n =>
153
        var event = nextResourceEvent
154
        publisher ! Message(event.toBytes,
155
          "%s.%s.%s".format(MessagingNames.RES_EVENT_KEY,event.clientId, event.resource))
156
    }
157
  }
158
}
159

    
160
object RandomEventGen extends RandomEventGenerator {
161

    
162
  case class Config(var i: Boolean = false,
163
                    var u: Boolean = false,
164
                    var r: Boolean = false,
165
                    var nummsg: Int = 100)
166

    
167
  val config = new Config
168

    
169
  private val parser = new OptionParser("RandomEventGen") {
170
    opt("i", "im-events", "Generate IM events", {config.i = true})
171
    opt("u", "user-create", "Generate IM events that create users", {config.u = true})
172
    opt("r", "resource-events", "Generate resource events", {config.r = true})
173
    arg("nummsgs", "Number of msgs to generate", {num: String => config.nummsg = Integer.parseInt(num)})
174
  }
175

    
176
  def main(args: Array[String]): Unit = {
177

    
178
    if (!parser.parse(args))
179
      errexit
180

    
181
    if (!config.i && !config.u && !config.r) {
182
      println("One of -i, -u, -r must be specified")
183
      errexit
184
    }
185

    
186
    println("Publishing %d msgs, hit Ctrl+c to stop".format(config.nummsg))
187
    if (config.r) genPublishResEvents(config.nummsg)
188
    if (config.u) initUsers
189
    if (config.i) genPublishUserEvents(config.nummsg)
190
  }
191
  
192
  private def errexit() = {
193
    print(parser.usage)
194
    System.exit(-1)
195
  }
196
}