cirrocumulus 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -7,9 +7,12 @@ gem "xmpp4r", "~> 0.5"
7
7
  gem "xmpp4r-simple", :git => 'git://github.com/blaine/xmpp4r-simple.git'
8
8
  gem "eventmachine"
9
9
  gem "deil_sexpistol", :require => "sexpistol"
10
+ gem 'guid'
10
11
 
11
12
  group :development do
13
+ #gem "shoulda", ">= 0"
14
+ gem "rdoc", "~> 3.12"
12
15
  gem "bundler", "~> 1.0.0"
13
- gem "jeweler", "~> 1.6.4"
14
- gem "rcov", ">= 0"
16
+ gem "jeweler", "~> 1.8.3"
17
+ #gem "simplecov", ">= 0"
15
18
  end
@@ -0,0 +1,43 @@
1
+ GIT
2
+ remote: git://github.com/blaine/xmpp4r-simple.git
3
+ revision: 92e2cd0002ec3a9a38506527e1a3a2d622408626
4
+ specs:
5
+ xmpp4r-simple (0.8.8)
6
+ xmpp4r (>= 0.3.2)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ activesupport (2.3.14)
12
+ deil_sexpistol (0.0.8)
13
+ eventmachine (0.12.10)
14
+ git (1.2.5)
15
+ guid (0.1.1)
16
+ jeweler (1.8.3)
17
+ bundler (~> 1.0)
18
+ git (>= 1.2.5)
19
+ rake
20
+ rdoc
21
+ json (1.6.5)
22
+ log4r (1.1.10)
23
+ rake (0.9.2.2)
24
+ rdoc (3.12)
25
+ json (~> 1.4)
26
+ systemu (2.4.2)
27
+ xmpp4r (0.5)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ activesupport (~> 2.3.11)
34
+ bundler (~> 1.0.0)
35
+ deil_sexpistol
36
+ eventmachine
37
+ guid
38
+ jeweler (~> 1.8.3)
39
+ log4r (~> 1.1.9)
40
+ rdoc (~> 3.12)
41
+ systemu
42
+ xmpp4r (~> 0.5)
43
+ xmpp4r-simple!
data/Rakefile CHANGED
@@ -21,28 +21,12 @@ Jeweler::Tasks.new do |gem|
21
21
  gem.description = "Engine for building your own agents, providing you base functionality for loading ontologies, communicating with other agents and parsing FIPA-ACL messages"
22
22
  gem.email = "deil@mneko.net"
23
23
  gem.authors = ["Anton Kosyakin"]
24
+ gem.required_ruby_version = '>= 1.9.2'
24
25
  # dependencies defined in Gemfile
25
26
  end
26
27
  Jeweler::RubygemsDotOrgTasks.new
27
28
 
28
- require 'rake/testtask'
29
- Rake::TestTask.new(:test) do |test|
30
- test.libs << 'lib' << 'test'
31
- test.pattern = 'test/**/test_*.rb'
32
- test.verbose = true
33
- end
34
-
35
- require 'rcov/rcovtask'
36
- Rcov::RcovTask.new do |test|
37
- test.libs << 'test'
38
- test.pattern = 'test/**/test_*.rb'
39
- test.verbose = true
40
- test.rcov_opts << '--exclude "gems/*"'
41
- end
42
-
43
- task :default => :test
44
-
45
- require 'rake/rdoctask'
29
+ require 'rdoc/task'
46
30
  Rake::RDocTask.new do |rdoc|
47
31
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
32
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.2
1
+ 0.6.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "cirrocumulus"
8
- s.version = "0.5.2"
8
+ s.version = "0.6.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Anton Kosyakin"]
12
- s.date = "2011-12-01"
12
+ s.date = "2012-04-10"
13
13
  s.description = "Engine for building your own agents, providing you base functionality for loading ontologies, communicating with other agents and parsing FIPA-ACL messages"
14
14
  s.email = "deil@mneko.net"
15
15
  s.extra_rdoc_files = [
@@ -18,30 +18,44 @@ Gem::Specification.new do |s|
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
+ ".idea/.name",
22
+ ".idea/.rakeTasks",
23
+ ".idea/cirrocumulus.iml",
24
+ ".idea/encodings.xml",
25
+ ".idea/misc.xml",
26
+ ".idea/modules.xml",
27
+ ".idea/scopes/scope_settings.xml",
28
+ ".idea/vcs.xml",
29
+ ".idea/workspace.xml",
21
30
  "Gemfile",
31
+ "Gemfile.lock",
22
32
  "LICENSE.txt",
23
33
  "README.rdoc",
24
34
  "Rakefile",
25
35
  "VERSION",
26
36
  "cirrocumulus.gemspec",
37
+ "lib/.gitignore",
27
38
  "lib/cirrocumulus.rb",
28
39
  "lib/cirrocumulus/agent.rb",
29
40
  "lib/cirrocumulus/agent_wrapper.rb",
30
- "lib/cirrocumulus/engine.rb",
31
- "lib/cirrocumulus/kb.rb",
41
+ "lib/cirrocumulus/jabber_bus.rb",
32
42
  "lib/cirrocumulus/logger.rb",
43
+ "lib/cirrocumulus/message.rb",
33
44
  "lib/cirrocumulus/ontology.rb",
34
45
  "lib/cirrocumulus/rule_engine.rb",
35
46
  "lib/cirrocumulus/rule_server.rb",
36
47
  "lib/cirrocumulus/rules/engine.rb",
37
48
  "lib/cirrocumulus/rules/run_queue.rb",
38
49
  "lib/cirrocumulus/saga.rb",
50
+ "lib/test.rb",
51
+ "lib/test2.rb",
39
52
  "test/helper.rb",
40
53
  "test/test_cirrocumulus.rb"
41
54
  ]
42
55
  s.homepage = "http://github.com/deil/cirrocumulus"
43
56
  s.licenses = ["GPL-2"]
44
57
  s.require_paths = ["lib"]
58
+ s.required_ruby_version = Gem::Requirement.new(">= 1.9.2")
45
59
  s.rubygems_version = "1.8.10"
46
60
  s.summary = "Agent-based infrastructure management system"
47
61
 
@@ -56,9 +70,10 @@ Gem::Specification.new do |s|
56
70
  s.add_runtime_dependency(%q<xmpp4r-simple>, [">= 0"])
57
71
  s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
58
72
  s.add_runtime_dependency(%q<deil_sexpistol>, [">= 0"])
73
+ s.add_runtime_dependency(%q<guid>, [">= 0"])
74
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
59
75
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
60
- s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
61
- s.add_development_dependency(%q<rcov>, [">= 0"])
76
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
62
77
  else
63
78
  s.add_dependency(%q<activesupport>, ["~> 2.3.11"])
64
79
  s.add_dependency(%q<log4r>, ["~> 1.1.9"])
@@ -67,9 +82,10 @@ Gem::Specification.new do |s|
67
82
  s.add_dependency(%q<xmpp4r-simple>, [">= 0"])
68
83
  s.add_dependency(%q<eventmachine>, [">= 0"])
69
84
  s.add_dependency(%q<deil_sexpistol>, [">= 0"])
85
+ s.add_dependency(%q<guid>, [">= 0"])
86
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
70
87
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
71
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
72
- s.add_dependency(%q<rcov>, [">= 0"])
88
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
73
89
  end
74
90
  else
75
91
  s.add_dependency(%q<activesupport>, ["~> 2.3.11"])
@@ -79,9 +95,10 @@ Gem::Specification.new do |s|
79
95
  s.add_dependency(%q<xmpp4r-simple>, [">= 0"])
80
96
  s.add_dependency(%q<eventmachine>, [">= 0"])
81
97
  s.add_dependency(%q<deil_sexpistol>, [">= 0"])
98
+ s.add_dependency(%q<guid>, [">= 0"])
99
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
82
100
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
83
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
84
- s.add_dependency(%q<rcov>, [">= 0"])
101
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
85
102
  end
86
103
  end
87
104
 
@@ -0,0 +1,5 @@
1
+ config/*
2
+ ontologies/*
3
+ standalone/*
4
+ agent.rb
5
+ *.log
@@ -1,4 +1,2 @@
1
- require 'sexpistol'
2
- require 'xmpp4r'
3
- require 'xmpp4r-simple'
4
1
  require 'active_support'
2
+ require 'cirrocumulus/logger'
@@ -1,4 +1,6 @@
1
1
  require 'thread'
2
+ require 'systemu'
3
+ require_relative 'jabber_bus'
2
4
 
3
5
  module Agent
4
6
  class AgentInfo
@@ -138,18 +140,32 @@ module Agent
138
140
  end
139
141
 
140
142
  class Base
141
- attr_reader :identifier
143
+ attr_reader :identifier # identifier of running agent
142
144
  attr_reader :network_map
143
145
 
144
- def initialize(cm)
145
- Log4r::Logger['agent'].info('Initializing new agent')
146
+ def initialize(suffix = 'master')
147
+ Log4r::Logger['agent'].info('Hello world!')
146
148
 
147
- @cm = cm
148
- @identifier = cm.jid
149
149
  @ontologies = []
150
150
  @message_queues = {}
151
151
  @worker_threads = {}
152
152
  #@network_map = NetworkMap.new(self)
153
+
154
+ @suffix = suffix
155
+ @identifier = nil
156
+ @bus = nil
157
+ @incoming_queue = Queue.new
158
+ end
159
+
160
+ # Gets current platform (linux, freebsd, etc)
161
+ def platform
162
+ if RUBY_PLATFORM =~ /freebsd/
163
+ return 'freebsd'
164
+ elsif RUBY_PLATFORM =~ /linux/
165
+ return 'linux'
166
+ end
167
+
168
+ return 'unknown'
153
169
  end
154
170
 
155
171
  # Loads ontologies into agent
@@ -190,52 +206,86 @@ module Agent
190
206
  Log4r::Logger['agent'].info 'State restored successfully!'
191
207
  end
192
208
 
193
- # Starts message processing threads
194
- def start()
195
- start_workers()
209
+ # Just sends an ACL message to bus
210
+ def send_message(message)
211
+ @bus.send_message(message)
196
212
  end
197
213
 
198
- def send_message(message)
199
- @cm.send_message(message)
214
+ # Replies to specified message.
215
+ # Sends a reply to bus in reply to original message using sender, reply_with and conversation_in
216
+ def reply_to_message(reply, message)
217
+ reply.receiver = message.sender
218
+ reply.in_reply_to = message.reply_with
219
+ reply.conversation_id = message.conversation_id
220
+ @bus.send_message(reply)
200
221
  end
201
222
 
202
- def handle_message(message)
203
- #@network_map.handle_message(message, @cm)
223
+ # Start the agent!
224
+ def start()
225
+ suffix = default_ontology ? default_ontology.gsub('cirrocumulus-', '') : @suffix
226
+ _, hostname = systemu('hostname')
227
+ hostname.strip!
228
+ @identifier = '%s-%s' % [hostname, suffix]
229
+
230
+ @bus = JabberBus.new(@identifier)
231
+ @bus.start(self)
204
232
 
205
- self.ontologies.each {|ontology|
206
- if message.ontology == ontology.name || ontology.sagas.any? {|saga| saga.id == message.in_reply_to}
207
- @message_queues[ontology] << message
208
- break
209
- end
210
- }
233
+ start_workers
234
+ restore_state
235
+ main_loop
236
+ end
237
+
238
+ def process_incoming_message(message)
239
+ @incoming_queue << message
211
240
  end
212
241
 
213
242
  protected
214
243
 
215
- attr_reader :cm
216
244
  attr_reader :ontologies
217
245
 
218
246
  def start_workers()
219
247
  self.ontologies.each do |ontology|
220
248
  @worker_threads[ontology] = Thread.new do
221
- Log4r::Logger['agent'].info "Starting worker for ontology %s" % [ontology.name]
222
- process_ontology(ontology, @message_queues[ontology])
249
+ Log4r::Logger['agent'].info 'Starting worker for ontology %s' % [ontology.name]
250
+ ontology_loop(ontology, @message_queues[ontology])
223
251
  end
224
252
  end
225
253
  end
226
254
 
227
- def process_ontology(ontology, queue)
255
+ def ontology_loop(ontology, queue)
228
256
  while true do
229
257
  message = queue.pop(true) rescue nil
230
- begin
231
- ontology.handle_incoming_message(message, nil) if message
232
- rescue Exception => e
233
- Log4r::Logger['agent'].warn "failed to handle incoming message for ontology %s: %s" % [ontology.name, e.to_s]
234
- Log4r::Logger['agent'].warn e.backtrace.to_s
258
+
259
+ if message
260
+ begin
261
+ ontology.handle_incoming_message(message, nil)
262
+ rescue Exception => e
263
+ Log4r::Logger['agent'].warn "failed to handle incoming message for ontology %s: %s" % [ontology.name, e.to_s]
264
+ Log4r::Logger['agent'].warn e.backtrace.to_s
265
+ end
266
+ else
267
+ ontology.tick()
268
+ sleep 0.2
235
269
  end
270
+ end
271
+ end
272
+
273
+ def main_loop
274
+ while true
275
+ message = @incoming_queue.pop(true) rescue nil
276
+
277
+ if message
278
+ next if (message.sender == self.identifier) && !(message.receiver == self.identifier)
236
279
 
237
- ontology.tick()
238
- sleep 0.5
280
+ ontologies.each do |ontology|
281
+ if message.ontology == ontology.name || ontology.sagas.any? {|saga| [message.in_reply_to, message.conversation_id].include?(saga.id) }
282
+ @message_queues[ontology] << message
283
+ break
284
+ end
285
+ end
286
+ else # sleep if no messages available
287
+ sleep 0.2
288
+ end
239
289
  end
240
290
  end
241
291
  end
@@ -9,8 +9,6 @@ end
9
9
  require 'yaml'
10
10
  require 'cirrocumulus'
11
11
  require 'cirrocumulus/logger'
12
- require 'cirrocumulus/engine'
13
- require 'cirrocumulus/kb'
14
12
  require 'cirrocumulus/ontology'
15
13
  require 'cirrocumulus/agent'
16
14
 
@@ -45,6 +43,7 @@ ontologies.each do |ontology_name|
45
43
  require File.join(AGENT_ROOT, 'ontologies', ontology_name.underscore)
46
44
  end
47
45
 
46
+ =begin
48
47
  kb_name = agent_config['kb']
49
48
  kb = if kb_name
50
49
  puts "Will load knowledge base %s" % kb_name
@@ -53,12 +52,12 @@ kb = if kb_name
53
52
  else
54
53
  Kb.new
55
54
  end
55
+ =end
56
56
 
57
- cm = Cirrocumulus.new('master')
58
- a = Agent::Base.new(cm)
59
- a.load_ontologies(agent_config['ontologies'])
60
57
  begin
61
- cm.run(a, kb)
58
+ a = Agent::Base.new
59
+ a.load_ontologies(agent_config['ontologies'])
60
+ a.start
62
61
  rescue Exception => e
63
62
  puts 'Got an error:'
64
63
  puts e
@@ -0,0 +1,140 @@
1
+ require 'xmpp4r'
2
+ require 'xmpp4r-simple'
3
+ require 'guid'
4
+ require 'sexpistol'
5
+ require_relative 'message'
6
+
7
+ class JabberBus
8
+ attr_reader :jid
9
+
10
+ def initialize(jid)
11
+ @jid = jid
12
+ @send_queue = Queue.new
13
+
14
+ Log4r::Logger['bus'].info 'will use Jabber for agent communications'
15
+ end
16
+
17
+ def connected?
18
+ @jabber && @jabber.connected?
19
+ end
20
+
21
+ def connect
22
+ Log4r::Logger['bus'].info "logging to #{JABBER_SERVER} as #{jid}"
23
+
24
+ begin
25
+ full_jid = jid + "@" + JABBER_SERVER
26
+ @jabber = Jabber::Simple.new(full_jid, JABBER_DEFAULT_PASSWORD)
27
+ rescue Errno::ECONNREFUSED => ex
28
+ Log4r::Logger['bus'].warn 'connection refused' and return false
29
+ rescue Jabber::ClientAuthenticationFailure => ex
30
+ Log4r::Logger['bus'].warn 'got Jabber::ClientAuthenticationFailure'
31
+ Log4r::Logger['bus'].info 'using default password to register new account'
32
+
33
+ client = Jabber::Client.new(full_jid)
34
+ client.connect()
35
+ client.register(JABBER_DEFAULT_PASSWORD) #, {'username' => full_jid, 'password' => JABBER_DEFAULT_PASSWORD})
36
+ client.close()
37
+ @jabber = Jabber::Simple.new(full_jid, JABBER_DEFAULT_PASSWORD)
38
+ end
39
+
40
+ if connected?
41
+ Log4r::Logger['bus'].info 'joining ' + JABBER_CONFERENCE
42
+ @jabber.send!("<presence to='#{JABBER_CONFERENCE}/#{@jid}' />")
43
+ true
44
+ else
45
+ false
46
+ end
47
+ rescue
48
+ false
49
+ end
50
+
51
+ def start(agent)
52
+ thrd = Thread.new do
53
+ s = Sexpistol.new
54
+ while true do
55
+ begin
56
+ if connected?
57
+ @jabber.received_messages do |message|
58
+ # <fipa-message ontology="cirrocumulus-cloud" act="inform" receiver="sapco-cloud"><content>q</content></fipa-message>
59
+ next unless message.x('jabber:x:delay').nil?
60
+
61
+ begin
62
+ xml = Hash.from_xml(message.body)['fipa_message']
63
+ content_raw = xml['content']
64
+ content = s.parse_string(content_raw)
65
+ acl = Cirrocumulus::Message.new(message.from.resource, xml['act'], content)
66
+ acl.receiver = xml['receiver']
67
+ acl.ontology = xml['ontology']
68
+ acl.reply_with = xml['reply_with']
69
+ acl.in_reply_to = xml['in_reply_to']
70
+ acl.conversation_id = xml['conversation_id']
71
+ flatten_message_content(acl)
72
+
73
+ #Log4r::Logger['bus'].debug(acl.inspect)
74
+ agent.process_incoming_message(acl)
75
+ rescue Exception => ex
76
+ p ex
77
+ p ex.backtrace
78
+ end
79
+ end
80
+
81
+ while true do
82
+ message = @send_queue.pop(true) rescue nil
83
+ break if message.nil?
84
+
85
+ send_message_actual(message)
86
+ end
87
+ else
88
+ sleep 5 unless connect
89
+ end
90
+
91
+ sleep 0.5
92
+ rescue Exception => ex
93
+ puts ex.to_s
94
+ puts ex.backtrace.to_s
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def send_message(message)
101
+ @send_queue << message
102
+ end
103
+
104
+ private
105
+
106
+ def flatten_message_content(message)
107
+ if !message.content.is_a?(Array)
108
+ message.content = [message.content]
109
+ else
110
+ while message.content.is_a?(Array) && message.content.size == 1 && message.content.first.is_a?(Array)
111
+ message.content = message.content.first
112
+ end
113
+ end
114
+ end
115
+
116
+ def send_message_actual(message)
117
+ message_content = message.content if message.content.is_a?(String)
118
+ message_content = Sexpistol.new.to_sexp(message.content) if message.content.is_a?(Array)
119
+
120
+ text = '<fipa-message ontology="%s"' % message.ontology
121
+ text += ' receiver="%s"' % message.receiver if message.receiver
122
+ text += ' act="%s"' % message.act
123
+ text += ' reply-with="%s"' % message.reply_with if message.reply_with
124
+ text += ' in-reply-to="%s"' % message.in_reply_to if message.in_reply_to
125
+ text += ' conversation-id="%s"' % message.conversation_id if message.conversation_id
126
+ text += '><content>%s</content></fipa-message>' % message_content
127
+ @jabber.send!('<message type="groupchat" to="%s" id="%s"><body>%s</body></message>' % [
128
+ JABBER_CONFERENCE,
129
+ Guid.new.to_s.gsub('-', ''),
130
+ text.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;').gsub('"', '&quot;')
131
+ ])
132
+
133
+ true
134
+ rescue Exception => ex
135
+ puts ex.to_s
136
+ puts ex.backtrace.to_s
137
+ false
138
+ end
139
+
140
+ end