cirrocumulus 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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