Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (6.3 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
import gr.grnet.aquarium.logic.accounting.Policy
45

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

    
54
  val userIds = 1 to 1000
55
  val clientIds = 1 to 4
56
  val vmIds = 1 to 4000
57
  val resources = Policy.policy.resources.map{r => r.name}
58
  val tsFrom = 1293840000000L //1/1/2011 0:00:00 GMT
59
  val tsTo = 1325376000000L   //1/1/2012 0:00:00 GMT
60
  val eventVersion = 1 to 4
61

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
161
object RandomEventGen extends RandomEventGenerator {
162

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

    
168
  val config = new Config
169

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

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

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

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

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