nuri 0.5.2 → 0.5.3

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