nuri 0.5.2 → 0.5.3

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.
@@ -30,19 +30,22 @@ end
30
30
 
31
31
  if $0 == __FILE__
32
32
  if ARGV.length < 2
33
- puts "Usage: install_module <address> [port] <module-name> ..."
33
+ puts "Usage: #{$0.split('/').last} <address>:[port] <module-name>+
34
+
35
+ "
34
36
  exit(1)
35
37
  end
36
38
 
37
39
  DefaultPort = 1314
38
40
 
39
- address = ARGV.shift
40
- port = (ARGV.length >= 2 ? ARGV.shift : DefaultPort)
41
+ address, port = ARGV.shift.split(':', 2)
42
+ port = port.to_s.to_i
43
+ port = DefaultPort unless port > 0
41
44
  modules = ARGV
42
45
  missing = modules.select { |mod| not ::File.directory?(mod) }
43
46
  modules = modules - missing
44
47
 
45
- success = Nuri::Util.install_modules(address, port, modules),
48
+ success = Nuri::Util.install_modules(address, port, modules)
46
49
  output = {
47
50
  :status => success,
48
51
  :installed_modules => modules,
@@ -3,10 +3,10 @@
3
3
  require 'rubygems'
4
4
  require 'json'
5
5
 
6
- module Sfp
6
+ module Nuri
7
7
  end
8
8
 
9
- module Sfp::Graph
9
+ module Nuri::Graph
10
10
  ActionColor = 'white'
11
11
  ActionLabelWithParameters = false
12
12
 
@@ -140,7 +140,8 @@ end
140
140
 
141
141
  def main
142
142
  if ARGV.length < 1
143
- puts "Convert SFP plan to an image graph with Graphviz (dot).\n\nUsage: sfw2dot.rb <input-file> [output-file]\n\n"
143
+ puts "Convert SFP plan to a PNG image graph using Graphviz library.
144
+ Usage: #{$0.split('/').last} <input-file> [output-file]\n\n"
144
145
  exit
145
146
  end
146
147
 
@@ -151,11 +152,11 @@ def main
151
152
  dot = ""
152
153
  case json["type"]
153
154
  when 'partial-order', 'parallel'
154
- dot = Sfp::Graph::partial2dot(json)
155
+ dot = Nuri::Graph::partial2dot(json)
155
156
  when 'sequential'
156
- dot = Sfp::Graph::sequential2dot(json)
157
+ dot = Nuri::Graph::sequential2dot(json)
157
158
  when 'stage'
158
- dot = Sfp::Graph::stage2dot(json)
159
+ dot = Nuri::Graph::stage2dot(json)
159
160
  else
160
161
  throw Exception, "Unrecognised type of workflow: #{json['type']}"
161
162
  end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'uri'
4
+ require 'net/http'
5
+
6
+ module Nuri
7
+ module Util
8
+ def self.delete_module(address, port, modules, protocol="http")
9
+ def self.send_request(url)
10
+ uri = URI.parse(url)
11
+ http = Net::HTTP.new(uri.host, uri.port)
12
+ request = Net::HTTP::Delete.new(uri.request_uri)
13
+ response = http.request(request)
14
+ (response.code == '200')
15
+ end
16
+ if modules.length <= 0
17
+ send_request("#{protocol}://#{address}:#{port}/modules")
18
+ else
19
+ modules.each do |mod|
20
+ return false if not send_request("#{protocol}://#{address}:#{port}/modules/#{mod}")
21
+ end
22
+ true
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ if $0 == __FILE__
29
+ DefaultPort = 1314
30
+
31
+ if ARGV.length < 1
32
+ puts "Usage: delete_modules <address>:[port] [module-name]*"
33
+ exit(1)
34
+ end
35
+
36
+ address, port = ARGV.shift.split(':', 2)
37
+ port = port.to_s.to_i
38
+ port = DefaultPort unless port > 0
39
+
40
+ if Nuri::Util.delete_module(address, port, ARGV)
41
+ puts '{"status":"ok"}'
42
+ else
43
+ puts '{"status":"failed"}'
44
+ end
45
+ end
@@ -1,3 +1,4 @@
1
1
  *cell*
2
2
  *.log
3
3
  *.log.*
4
+ *idol*
@@ -1,66 +1,22 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- def generate(number_apps)
4
- header = 'include "../modules/node/node.sfp"
5
- include "../modules/mockcloud/mockcloud.sfp"
6
- include "../modules/vm/vm.sfp"
7
- include "../modules/apache/apache.sfp"
8
- include "../modules/mysql/mysql.sfp"
9
- include "../modules/wordpresscluster/wordpresscluster.sfp"
3
+ require 'erb'
4
+ require 'ostruct'
10
5
 
11
- proxy isa Node {
12
- sfpAddress is "localhost"
13
- cloud isa MockCloud
14
- }
15
- '
16
- vmlb = 'vmlb isa VM {
17
- apache isa Apache {
18
- running is true
19
- is_load_balancer is true
20
- lb_members is (%members%)
21
- }
22
- }'
23
- vmapp = '%vmapp% isa VM {
24
- apache isa Apache {
25
- running is true
26
- }
27
- wp_web isa WordpressWeb {
28
- installed is true
29
- http is %vmapp%.apache
30
- database is vmdb.wp_db
31
- }
32
- }'
33
- vmdb = 'vmdb isa VM {
34
- mysql isa Mysql {
35
- running is true
36
- }
37
- wp_db isa WordpressDB {
38
- installed is true
39
- mysql is vmdb.mysql
40
- }
41
- }'
42
- output = ''
43
- members = ''
44
- global = "global {\n"
45
- 1.upto(number_apps) do |i|
46
- name = "vmapp#{i}"
47
- output += vmapp.gsub(/%vmapp%/, name) + "\n"
48
- members += "#{name},"
49
- global += "\tif vmlb.apache.running is true then #{name}.apache.running is true\n"
50
- global += "\tif #{name}.apache.running is true then vmdb.mysql.running is true\n"
6
+ class ErbBinding < OpenStruct
7
+ def render(template)
8
+ ERB.new(template).result(binding)
51
9
  end
52
- global += "}\n"
53
- output = header +
54
- vmlb.sub(/%members%/, members.chop) + "\n" +
55
- output + vmdb + "\n" + global
56
- output
57
10
  end
58
11
 
59
- if $0 == __FILE__
60
- if ARGV[0] == 'help'
61
- puts "Usage: generator.rb [total-app-layer]"
62
- else
63
- number_apps = (ARGV.length > 0 ? ARGV[0].to_i : 3)
64
- puts generate(number_apps)
12
+ if ARGV.length <= 0
13
+ puts "Usage: generator.rb <template-file> [key=value]*"
14
+ else
15
+ template = File.read(ARGV.shift)
16
+ data = {}
17
+ ARGV.each do |arg|
18
+ key, value = arg.split('=')
19
+ data[key] = value
65
20
  end
21
+ puts ErbBinding.new(data).render(template)
66
22
  end
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ def generate(number_apps)
4
+ header = 'include "../modules/node/node.sfp"
5
+ include "../modules/mockcloud/mockcloud.sfp"
6
+ include "../modules/vm/vm.sfp"
7
+ include "../modules/apache/apache.sfp"
8
+ include "../modules/mysql/mysql.sfp"
9
+ include "../modules/wordpresscluster/wordpresscluster.sfp"
10
+
11
+ proxy isa Node {
12
+ sfpAddress is "localhost"
13
+ cloud isa MockCloud
14
+ }
15
+ '
16
+ vmlb = 'vmlb isa VM {
17
+ apache isa Apache {
18
+ running is true
19
+ is_load_balancer is true
20
+ lb_members is (%members%)
21
+ }
22
+ }'
23
+ vmapp = '%vmapp% isa VM {
24
+ apache isa Apache {
25
+ running is true
26
+ }
27
+ wp_web isa WordpressWeb {
28
+ installed is true
29
+ http is %vmapp%.apache
30
+ database is vmdb.wp_db
31
+ }
32
+ }'
33
+ vmdb = 'vmdb isa VM {
34
+ mysql isa Mysql {
35
+ running is true
36
+ }
37
+ wp_db isa WordpressDB {
38
+ installed is true
39
+ mysql is vmdb.mysql
40
+ }
41
+ }'
42
+ output = ''
43
+ members = ''
44
+ global = "global {\n"
45
+ 1.upto(number_apps) do |i|
46
+ name = "vmapp#{i}"
47
+ output += vmapp.gsub(/%vmapp%/, name) + "\n"
48
+ members += "#{name},"
49
+ global += "\tif vmlb.apache.running is true then #{name}.apache.running is true\n"
50
+ global += "\tif #{name}.apache.running is true then vmdb.mysql.running is true\n"
51
+ end
52
+ global += "}\n"
53
+ output = header +
54
+ vmlb.sub(/%members%/, members.chop) + "\n" +
55
+ output + vmdb + "\n" + global
56
+ output
57
+ end
58
+
59
+ if $0 == __FILE__
60
+ if ARGV[0] == 'help'
61
+ puts "Usage: generator.rb [total-app-layer]"
62
+ else
63
+ number_apps = (ARGV.length > 0 ? ARGV[0].to_i : 3)
64
+ puts generate(number_apps)
65
+ end
66
+ end
@@ -0,0 +1,25 @@
1
+ /***
2
+ *
3
+ * Required parameters:
4
+ * - total : number of slaves
5
+ *
6
+ */
7
+
8
+ include "modules/vm/vm.sfp"
9
+ include "modules/mockcloud/mockcloud.sfp"
10
+ include "modules/hadoop2/hadoop2.sfp"
11
+ proxy isa Node {
12
+ sfpAddress is "localhost"
13
+ cloud isa MockCloud
14
+ }
15
+ master isa VM {
16
+ hadoop isa Hadoop2Master
17
+ }
18
+ slave1 isa VM {
19
+ hadoop isa Hadoop2Slave {
20
+ master is master.hadoop
21
+ }
22
+ }
23
+ <% (2..total.to_i).each do |i| %>
24
+ slave<%= i %> extends slave1
25
+ <% end %>
@@ -53,10 +53,8 @@ module Nuri
53
53
  end
54
54
 
55
55
  # internal dependencies
56
- libdir = File.expand_path(File.dirname(__FILE__))
57
- require libdir + '/nuri/constraint_helper.rb'
58
- require libdir + '/nuri/helper.rb'
59
- require libdir + '/nuri/orchestrator.rb'
60
- require libdir + '/nuri/choreographer.rb'
61
- #require libdir + '/nuri/server.rb'
62
- require libdir + '/nuri/master.rb'
56
+ libdir = File.dirname(__FILE__) << '/nuri'
57
+ ['constraint_helper.rb', 'helper.rb', 'orchestrator.rb',
58
+ 'choreographer.rb', 'master.rb'].each do |file|
59
+ require "#{libdir}/#{file}"
60
+ end
@@ -42,7 +42,7 @@ module Nuri::Choreographer
42
42
  local_bsigs[name] = local
43
43
  end
44
44
  end
45
- puts "Choreographing: #{choreographing_time}"
45
+ puts "Choreographing " + format_benchmark(choreographing_time)
46
46
 
47
47
  # bsig
48
48
  local_bsigs
@@ -62,7 +62,7 @@ module Nuri::Choreographer
62
62
  address = @model.at?("$.#{name}.sfpAddress")
63
63
  port = @model.at?("$.#{name}.sfpPort")
64
64
  if !address.is_a?(String) or address.length <= 0 or !port.is_a?(Fixnum) or port <= 0
65
- puts "Agent #{name} is not exist!".yellow
65
+ puts (p[:color] ? "[Warn]".yellow : "[Warn]") + " Agent #{name} is not exist!"
66
66
  next
67
67
  end
68
68
 
@@ -73,9 +73,9 @@ module Nuri::Choreographer
73
73
  rescue
74
74
  end
75
75
  if code == '200'
76
- puts "Deploying BSig model to #{name}@#{address}:#{port} [OK]".green
76
+ puts "Deploying BSig model to #{name}@#{address}:#{port} " + (p[:color] ? "[OK]".green : "[OK]")
77
77
  else
78
- $stderr.puts "Deploying BSig model to #{name}@#{address}:#{port} [Failed]".red
78
+ $stderr.puts "Deploying BSig model to #{name}@#{address}:#{port} " + (p[:color] ? "[Failed]".red : "[Failed]")
79
79
  success = false
80
80
  end
81
81
  end
@@ -106,9 +106,9 @@ module Nuri::Choreographer
106
106
  rescue
107
107
  end
108
108
  if code == '200'
109
- puts "Sending model of #{name} to #{address}:#{port} [OK]".green
109
+ puts "Sending model of #{name} to #{address}:#{port} " + (p[:color] ? "[OK]".green : "[OK]")
110
110
  else
111
- $stderr.puts "Sending model of #{name} to #{address}:#{port} [Failed]".red
111
+ $stderr.puts "Sending model of #{name} to #{address}:#{port} " + (p[:color] ? "[Failed]".red : "[Failed]")
112
112
  return false
113
113
  end
114
114
  end
@@ -139,9 +139,9 @@ module Nuri::Choreographer
139
139
  rescue
140
140
  end
141
141
  if code1 == '200' and code2 == '200'
142
- puts "Purging BSig model: #{name}@#{address}:#{port} [OK]".green
142
+ puts "Purging BSig model: #{name}@#{address}:#{port} " + (p[:color] ? "[OK]".green : "[OK]")
143
143
  else
144
- $stderr.puts "Purging BSig model: #{name}@#{address}:#{port} [Failed]".red
144
+ $stderr.puts "Purging BSig model: #{name}@#{address}:#{port} " + (p[:color] ? "[Failed]".red : "[Failed]")
145
145
  success = false
146
146
  end
147
147
  end
@@ -18,16 +18,23 @@ module Sfp::Helper
18
18
  when 'null'
19
19
  nil
20
20
  when 'any_value'
21
- '$.Any:' + value['_isa']
21
+ isa = value['_isa']
22
+ if isa.is_a?(String) and isa.isref
23
+ '$.Any' + '.' + isa[2, isa.length-2]
24
+ else
25
+ '$.Any'
26
+ end
22
27
  when 'set'
23
28
  value['_values']
24
29
  else
25
30
  value
26
31
  end
27
32
  elsif value.is_a?(Sfp::Unknown)
28
- '$.Unknown:' + value.type.to_s
33
+ t = value.type.to_s
34
+ "$.Unknown" + (t.length > 2 ? ".#{t[2, t.length-2]}" : "")
29
35
  elsif value.is_a?(Sfp::Undefined)
30
- '$.Undefined:' + value.type.to_s
36
+ t = value.type.to_s
37
+ "$.Undefined" + (t.length > 2 ? ".#{t[2, t.length-2]}" : "")
31
38
  else
32
39
  value
33
40
  end
@@ -12,6 +12,8 @@ class Nuri::Master
12
12
  CloudSchema = '$.Cloud'
13
13
  VMSchema = '$.VM'
14
14
 
15
+ InstallModule = File.dirname(__FILE__) + '/../../bin/nuri-install-module'
16
+
15
17
  attr_reader :model
16
18
 
17
19
  def initialize(p={})
@@ -62,12 +64,16 @@ class Nuri::Master
62
64
  p[:sfp] = create_plan_task(p)
63
65
  p[:sas_post_processor] = SASPostProcessor
64
66
 
67
+ print "Planning "
68
+
65
69
  plan = nil
66
70
  planning_time = Benchmark.measure do
67
71
  planner = Sfp::Planner.new
68
72
  plan = planner.solve(p)
69
73
  end
70
- puts "Planning time (s): #{planning_time}"
74
+
75
+ print (p[:color] ? "[Finish] ".green : "[Finish] ")
76
+ puts format_benchmark(planning_time)
71
77
 
72
78
  plan
73
79
  end
@@ -122,12 +128,23 @@ class Nuri::Master
122
128
  end
123
129
 
124
130
  protected
131
+ def format_benchmark(benchmark)
132
+ "cpu-time: user=#{benchmark.cutime.round(2)} sys=#{benchmark.cstime.round(2)} total=#{benchmark.total.round(2)}"
133
+ end
134
+
125
135
  def create_plan_task(p={})
126
136
  task = get_schemata
127
137
 
128
- puts "Getting current state [WAIT]".yellow
129
- b = Benchmark.measure { task['initial'] = to_state('initial', get_state(p)) }
130
- puts "Getting current state [OK] : #{b}".green
138
+ print "Getting current state "
139
+ puts (p[:color] ? "[Wait]".yellow : "[Wait]")
140
+
141
+ b = Benchmark.measure do
142
+ task['initial'] = to_state('initial', get_state(p))
143
+ end
144
+
145
+ print "Getting current state "
146
+ print (p[:color] ? "[OK]".green : "[OK]")
147
+ puts " " + format_benchmark(b)
131
148
 
132
149
  task['initial'].accept(Sfp::Visitor::SfpGenerator.new(task))
133
150
  f1 = Sfp::Helper::SfpFlatten.new
@@ -149,17 +166,24 @@ class Nuri::Master
149
166
  dead_nodes.each_key { |name|
150
167
  task['initial'].delete(name)
151
168
  task['goal'].keep_if { |k,v| !(k =~ /(\$\.#{name}\.|\$\.#{name}$)/) }
152
- puts "[WARN] Removing node #{name} from the task.".red
169
+ print (p[:color] ? "[Warn]".red : "[Warn]")
170
+ puts " Removing node #{name} from the task."
153
171
  }
154
172
 
155
173
  # print the status of goal state
156
- puts "Goal state:".yellow
174
+ puts "Goal state:"
157
175
  goalgen.results.each { |k,v|
158
176
  next if k[0,1] == '_'
159
- print " #{k}: " + Sfp::Helper::Sfp2Ruby.val(v['_value']).to_s.green
177
+
178
+ print " #{k}: "
179
+ value = Sfp::Helper::Sfp2Ruby.val(v['_value']).to_s
180
+ print (p[:color] ? value.green : value) + " "
181
+
160
182
  if f1.results.has_key?(k) and f1.results[k] != v['_value']
161
- print " " + Sfp::Helper::Sfp2Ruby.val(f1.results[k]).to_s.red
183
+ value = Sfp::Helper::Sfp2Ruby.val(f1.results[k]).to_s
184
+ print (p[:color] ? value.red : value)
162
185
  end
186
+
163
187
  puts ""
164
188
  }
165
189
 
@@ -310,6 +334,15 @@ class Nuri::Master
310
334
  false
311
335
  end
312
336
 
337
+ ###############
338
+ #
339
+ # Push required modules to agent based on schemata available in agent's model
340
+ #
341
+ # @param agent_model agent's model
342
+ # @param address agent's address (IP or DNS address)
343
+ # @param port agent's port
344
+ #
345
+ ###############
313
346
  def push_modules(agent_model, address=nil, port=nil)
314
347
  if address.nil? or port.nil?
315
348
  return false if !agent_model.is_a?(Hash) or !agent_model['sfpAddress'].is_a?(String)
@@ -330,15 +363,20 @@ class Nuri::Master
330
363
  raise Exception, "Unable to get modules list from #{name}" if code.to_i != 200
331
364
 
332
365
  modules = JSON[body]
333
- list = ''
334
- schemata.each { |m|
335
- list += "#{m} " if File.exist?("#{@modules_dir}/#{m}") and
336
- (not modules.has_key?(m) or modules[m] != get_local_module_hash(m).to_s)
337
- }
366
+ tobe_installed_modules = []
367
+ schemata.each do |name|
368
+ module_dir = "#{@modules_dir}/#{name}"
369
+ if File.exist?(module_dir) and
370
+ ( not modules.has_key?(name) or modules[name] != get_local_module_hash(name).to_s )
371
+ tobe_installed_modules << name
372
+ end
373
+ end
338
374
 
339
- return true if list == ''
375
+ return true if tobe_installed_modules.length <= 0
340
376
 
341
- output = JSON.parse(`cd #{@modules_dir}; ./install_module #{address} #{port} #{list}`)
377
+ ### install new modules and replace old ones
378
+ list = tobe_installed_modules.join(" ")
379
+ output = JSON.parse(`cd #{@modules_dir}; #{InstallModule} #{address}:#{port} #{list}`)
342
380
  if output['installed_modules'].length > 0
343
381
  puts ("Push modules: " + output['installed_modules'].join(" ") + " to agent #{name} [OK]").green
344
382
  end