claudius 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +39 -0
- data/Rakefile +1 -0
- data/claudius.gemspec +24 -0
- data/examples/_ +0 -0
- data/examples/on_instance.rb +15 -0
- data/examples/simple_program.rb +16 -0
- data/examples/specify_instances.rb +29 -0
- data/lib/remote_execution/cloud_provider.rb +32 -0
- data/lib/remote_execution/provider.rb +53 -0
- data/lib/remote_execution/virtual_machine.rb +42 -0
- data/lib/tree_building/claudius.rb +109 -0
- data/lib/tree_building/concurrent_node.rb +60 -0
- data/lib/tree_building/event_machine_play.rb +20 -0
- data/lib/tree_building/execution_node.rb +45 -0
- data/lib/tree_building/node.rb +118 -0
- data/lib/tree_building/on_node.rb +60 -0
- data/test/execution_test.rb +56 -0
- data/test/gem_usage_test.rb +38 -0
- data/test/test.rb +46 -0
- data/test/test_local_execution.rb +20 -0
- metadata +155 -0
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.pem
|
2
|
+
.idea/*
|
3
|
+
lib/.idea/*
|
4
|
+
treeBuilding/.idea/*
|
5
|
+
user_config.json
|
6
|
+
*.gem
|
7
|
+
*.rbc
|
8
|
+
.bundle
|
9
|
+
.config
|
10
|
+
.yardoc
|
11
|
+
Gemfile.lock
|
12
|
+
InstalledFiles
|
13
|
+
_yardoc
|
14
|
+
coverage
|
15
|
+
doc/
|
16
|
+
lib/bundler/man
|
17
|
+
pkg
|
18
|
+
rdoc
|
19
|
+
doc
|
20
|
+
spec/reports
|
21
|
+
test/tmp
|
22
|
+
test/version_tmp
|
23
|
+
tmp
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 radk0s
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Claudius
|
2
|
+
|
3
|
+
Claudius is a easy-to-use domain specific language for clouds experiments. Language is build on [fog.io](http://fog.io), which enables flexible and powerfull way to manage virtual machine instances on various cloude poviders. Connections with virtual machines is based on ssh. To provide information experiment flow, DSL generates readable graph of execution.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
|
8
|
+
Install it as:
|
9
|
+
|
10
|
+
$ sudo gem install claudius-0.0.1.gem
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
Check doc [here](http://blostic.github.io/claudius).
|
15
|
+
|
16
|
+
|
17
|
+
## Documentation
|
18
|
+
|
19
|
+
Documemtation is autogenerated from examples by [Groc](https://github.com/nevir/groc).
|
20
|
+
To build doc you need [Node.js](http://nodejs.org/) and [Pygments](http://pygments.org/).
|
21
|
+
|
22
|
+
npm install -g groc
|
23
|
+
|
24
|
+
Generate to *doc* folder:
|
25
|
+
|
26
|
+
groc examples/* README.md
|
27
|
+
|
28
|
+
Generate to GitHub page:
|
29
|
+
|
30
|
+
groc --gh examples/* README.md
|
31
|
+
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
1. Fork it
|
36
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
37
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
38
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
39
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/claudius.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "claudius"
|
7
|
+
spec.version = "0.0.1"
|
8
|
+
spec.authors = ["radk0s", "blost"]
|
9
|
+
spec.email = ["rachamot@gmail.com"]
|
10
|
+
spec.description = "Write a gem description"
|
11
|
+
spec.summary = "Write a gem summary"
|
12
|
+
spec.homepage = "https://github.com/blostic/claudius"
|
13
|
+
spec.license = "MIT"
|
14
|
+
spec.files = `git ls-files`.split($/)
|
15
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
|
+
spec.require_paths = ["lib/tree_building","lib/remote_execution"]
|
18
|
+
|
19
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
20
|
+
spec.add_development_dependency "rake"
|
21
|
+
spec.add_runtime_dependency "fog"
|
22
|
+
spec.add_runtime_dependency "net-ssh"
|
23
|
+
spec.add_runtime_dependency "graph"
|
24
|
+
end
|
data/examples/_
ADDED
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
# Initiate experiment
|
3
|
+
# ---------
|
4
|
+
# Getting started Claudius is extremely simple. First example illustrates how to perform experiment which writes Hello World! to TestFile in your current directory
|
5
|
+
|
6
|
+
# To use the DSL in your code, please require the gem:
|
7
|
+
require 'claudius'
|
8
|
+
# We sepcified te __experiment__ with name "Hello". Tree which represents our experiment was returned after parse DSL.
|
9
|
+
execution_tree = experiment 'Hello' do
|
10
|
+
# __execute__ is a block where we can specify particular commands.
|
11
|
+
execute do
|
12
|
+
# Each starts with __ssh__ following by string represets command.
|
13
|
+
ssh "echo Hello World! > TestFile"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
# Initiate experiment
|
3
|
+
# ---------
|
4
|
+
#
|
5
|
+
# Getting started Claudius is extremely simple. First example illustrates how to perform experiment which writes Hello World! to TestFile in your current directory
|
6
|
+
#
|
7
|
+
# To use the DSL in your code, please require the gem:
|
8
|
+
require 'claudius'
|
9
|
+
# We sepcified te __experiment__ with name "Hello". Tree which represents our experiment was returned after parse DSL.
|
10
|
+
execution_tree = experiment 'Hello' do
|
11
|
+
# __execute__ is a block where we can specify particular commands.
|
12
|
+
execute do
|
13
|
+
# Each starts with __ssh__ following by string represets command.
|
14
|
+
ssh "echo Hello World! > TestFile"
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
# Specify instances
|
3
|
+
# ---------
|
4
|
+
# To conduct an experiment remotely, You should define set of machines, which you would like to use. Claudius allows you to define 2 types of hosts - ones which are going to be created in clouds environment, and others which are already established (and you have access to them). To define machine and to maintain connection with them you should provide required parameters. For your convenience, you may store all yours parameters in json file, and recall them as it is presented in example.
|
5
|
+
#
|
6
|
+
require 'claudius'
|
7
|
+
config = load_config('./user_config.json')
|
8
|
+
experiment 'Hello' do
|
9
|
+
define_providers do
|
10
|
+
cloud('aws', :provider => config['provider'],
|
11
|
+
:region =>config['region'],
|
12
|
+
:endpoint => 'https://ec2.eu-west-1.amazonaws.com/',
|
13
|
+
:aws_access_key_id => config['aws_access_key_id'],
|
14
|
+
:aws_secret_access_key => config['aws_secret_access_key'])
|
15
|
+
.create_instances(['t1.micro=>in1'],
|
16
|
+
:username => 'ubuntu',
|
17
|
+
:private_key_path =>'./Piotr-key-pair-irleand.pem',
|
18
|
+
:key_name => 'Piotr-key-pair-irleand',
|
19
|
+
:groups => ['Piotr-irleand'])
|
20
|
+
manual('kali', '172.16.0.109', 'root', :password => 'toor')
|
21
|
+
end
|
22
|
+
foreach ['kali', 'in1'] do |instance|
|
23
|
+
on instance do
|
24
|
+
execute do
|
25
|
+
ssh "echo Hello World! > TestFile"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'fog'
|
2
|
+
require 'net/ssh'
|
3
|
+
|
4
|
+
class CloudProvider
|
5
|
+
attr_accessor :provider_name, :provider, :virtual_machines, :instances
|
6
|
+
|
7
|
+
def initialize(name, *args)
|
8
|
+
@provider_name = name
|
9
|
+
@provider = Fog::Compute.new(*args)
|
10
|
+
@virtual_machines = Hash.new
|
11
|
+
@instances = Array.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_instances(instances_types, *parameters)
|
15
|
+
parameters = parameters[0]
|
16
|
+
instances_types.each do |instance_type|
|
17
|
+
puts 'creating machine: ' + instance_type
|
18
|
+
parameters.store(:flavor_id, instance_type.split('=>').first)
|
19
|
+
name = ("#{@provider_name}:" + instance_type).split('=>')
|
20
|
+
machine = @provider.servers.bootstrap(parameters)
|
21
|
+
@instances.push(machine)
|
22
|
+
machine_id = @provider.servers.get(machine.id)
|
23
|
+
vm = VirtualMachine.new(machine_id.public_ip_address, parameters[:username], :keys => parameters[:private_key_path])
|
24
|
+
@virtual_machines.store(name.last, vm)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def destroy
|
29
|
+
@instances.each { |instance| instance.destroy }
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'virtual_machine.rb'
|
2
|
+
require 'cloud_provider.rb'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
$virtual_machines = Hash.new
|
6
|
+
|
7
|
+
class MachineManager
|
8
|
+
attr_accessor :cloud_providers
|
9
|
+
|
10
|
+
def initialize(&block)
|
11
|
+
@virtual_machines = Hash.new
|
12
|
+
@cloud_providers = Array.new
|
13
|
+
instance_eval(&block) if block
|
14
|
+
@cloud_providers.each do |provider|
|
15
|
+
@virtual_machines = @virtual_machines.merge(provider.virtual_machines)
|
16
|
+
end
|
17
|
+
$virtual_machines = @virtual_machines
|
18
|
+
puts $virtual_machines
|
19
|
+
if @cloud_providers.length != 0
|
20
|
+
wait_for_sshable
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def manual(name, host, username, *args)
|
25
|
+
vm = VirtualMachine.new(host, username, *args)
|
26
|
+
@virtual_machines.store(name, vm)
|
27
|
+
end
|
28
|
+
|
29
|
+
def cloud(name, *args)
|
30
|
+
cloud_provider = CloudProvider.new(name, *args)
|
31
|
+
@cloud_providers.push(cloud_provider)
|
32
|
+
cloud_provider
|
33
|
+
end
|
34
|
+
|
35
|
+
def wait_for_sshable
|
36
|
+
cloud_providers.each do |provider|
|
37
|
+
provider.instances.each do |server|
|
38
|
+
server.wait_for { print '.'; sshable? }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def load_config( filename )
|
46
|
+
File.open( filename, 'r' ) { |file_name|
|
47
|
+
JSON.load(file_name)
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def define_providers (&block)
|
52
|
+
MachineManager.new &block
|
53
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'net/ssh'
|
2
|
+
|
3
|
+
def s_ssh(session, commands)
|
4
|
+
commands.each do |command|
|
5
|
+
session.exec(command)
|
6
|
+
end
|
7
|
+
session.loop
|
8
|
+
end
|
9
|
+
|
10
|
+
class VirtualMachine
|
11
|
+
attr_accessor :host, :username, :args, :log_file, :active
|
12
|
+
|
13
|
+
def initialize(host, username, *args)
|
14
|
+
@host = host
|
15
|
+
@username = username
|
16
|
+
args[0].store(:timeout, 5)
|
17
|
+
@args = args
|
18
|
+
@active = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"[host: #{host}, user: #{username}]"
|
23
|
+
end
|
24
|
+
|
25
|
+
def ssh_test(session,command)
|
26
|
+
res = session.exec!(command)
|
27
|
+
puts res
|
28
|
+
if (res!='' and res!="attributes.json\n")
|
29
|
+
@active = true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def invoke(commands)
|
34
|
+
Net::SSH.start(host, username, *args) do |ssh|
|
35
|
+
commands.each do |command|
|
36
|
+
print command , "\n"
|
37
|
+
s_ssh ssh, command
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'concurrent_node.rb'
|
2
|
+
require 'on_node.rb'
|
3
|
+
require 'execution_node.rb'
|
4
|
+
|
5
|
+
def experiment(name, &block)
|
6
|
+
experiment = Experiment.new(name, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
class Experiment
|
10
|
+
#attr_accessor :child_node
|
11
|
+
|
12
|
+
$child_node
|
13
|
+
$current_node = nil
|
14
|
+
$tmp_asynchronously = false
|
15
|
+
$tmp_safely = false
|
16
|
+
$tmp_execution_place = 'localhost'
|
17
|
+
$in_after_scope = false
|
18
|
+
$in_before_scope = false
|
19
|
+
|
20
|
+
$root
|
21
|
+
|
22
|
+
def initialize(name, &block)
|
23
|
+
$root = Node.new(nil,block)
|
24
|
+
$current_node = $root
|
25
|
+
$root.name = name
|
26
|
+
instance_eval(&block) if block
|
27
|
+
$root.print_tree
|
28
|
+
run_with_time
|
29
|
+
end
|
30
|
+
|
31
|
+
def asynchronously
|
32
|
+
$child_node = ConcurrentNode.new($current_node, nil)
|
33
|
+
$current_node.node_list.push($child_node)
|
34
|
+
$current_node = $child_node
|
35
|
+
end
|
36
|
+
|
37
|
+
def safely
|
38
|
+
puts 'should be safely'
|
39
|
+
end
|
40
|
+
|
41
|
+
def before(*args, &block)
|
42
|
+
$in_before_scope = true
|
43
|
+
yield
|
44
|
+
$in_before_scope = false
|
45
|
+
end
|
46
|
+
|
47
|
+
def after(*args, &block)
|
48
|
+
$in_after_scope = true
|
49
|
+
yield
|
50
|
+
$in_after_scope = false
|
51
|
+
end
|
52
|
+
|
53
|
+
def foreach(parameters, *args, &block)
|
54
|
+
puts $current_node.name
|
55
|
+
parameters.each do |parameter|
|
56
|
+
$child_node = Node.new($current_node, block)
|
57
|
+
$child_node.is_safely = $tmp_safely
|
58
|
+
$child_node.is_asynchronously = $tmp_asynchronously
|
59
|
+
$current_node.node_list.push($child_node)
|
60
|
+
$current_node = $child_node
|
61
|
+
block.call parameter
|
62
|
+
$current_node = $current_node.parent
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def on(instance, *args, &block)
|
67
|
+
$child_node = OnNode.new($current_node, instance, block)
|
68
|
+
|
69
|
+
$current_node.node_list.push($child_node)
|
70
|
+
$current_node = $child_node
|
71
|
+
block.call
|
72
|
+
$current_node = $current_node.parent
|
73
|
+
end
|
74
|
+
|
75
|
+
def concurrent(*args, &block)
|
76
|
+
$child_node = ConcurrentNode.new($current_node, block)
|
77
|
+
$current_node.node_list.push($child_node)
|
78
|
+
$current_node = $child_node
|
79
|
+
block.call
|
80
|
+
$current_node = $current_node.parent
|
81
|
+
end
|
82
|
+
|
83
|
+
def execute(*args, &block)
|
84
|
+
$child_node = ExecutionNode.new($current_node, block)
|
85
|
+
$child_node.is_safely = $tmp_safely
|
86
|
+
$child_node.is_asynchronously = $tmp_asynchronously
|
87
|
+
$current_node.node_list.push($child_node)
|
88
|
+
$current_node = $child_node
|
89
|
+
block.call
|
90
|
+
$current_node = $current_node.parent
|
91
|
+
end
|
92
|
+
|
93
|
+
def ssh(command)
|
94
|
+
if $in_before_scope
|
95
|
+
$current_node.before_list.push(command)
|
96
|
+
elsif $in_after_scope
|
97
|
+
$current_node.after_list.push(command)
|
98
|
+
else
|
99
|
+
$current_node.commands.push(command)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def run_with_time
|
104
|
+
result = $root.run(nil)
|
105
|
+
awesome_print result
|
106
|
+
return result
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'node.rb'
|
2
|
+
require 'graph'
|
3
|
+
|
4
|
+
class ConcurrentNode < Node
|
5
|
+
attr_accessor :instance
|
6
|
+
|
7
|
+
def initialize (parent, block)
|
8
|
+
super(parent, block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(instance)
|
12
|
+
pids = []
|
13
|
+
totalTime =
|
14
|
+
{
|
15
|
+
:name => self.name,
|
16
|
+
:before => 0,
|
17
|
+
:exec => [],
|
18
|
+
:after => 0
|
19
|
+
}
|
20
|
+
|
21
|
+
start = Time.now
|
22
|
+
before_list.each do |before_command|
|
23
|
+
if instance.nil?
|
24
|
+
puts `"#{before_command}"`
|
25
|
+
else
|
26
|
+
$virtual_machines[instance].invoke [[before_command]]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
finish = Time.now
|
30
|
+
|
31
|
+
totalTime[:before] = finish - start
|
32
|
+
|
33
|
+
node_list.each do |node|
|
34
|
+
pids << fork do
|
35
|
+
totalTime[:exec].push(node.run(instance))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
pids.each{|pid| Process.waitpid(pid)}
|
40
|
+
|
41
|
+
start = Time.now
|
42
|
+
after_list.each do |after_command|
|
43
|
+
if instance.nil?
|
44
|
+
puts `"#{after_command}"`
|
45
|
+
else
|
46
|
+
$virtual_machines[instance].invoke [[after_command]]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
finish = Time.now
|
50
|
+
|
51
|
+
totalTime[:after] = finish - start
|
52
|
+
return totalTime
|
53
|
+
end
|
54
|
+
|
55
|
+
def draw_block(graph)
|
56
|
+
graph.component << graph.node(self.id)
|
57
|
+
graph.node(self.id).label('Concurrently')
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'eventmachine'
|
5
|
+
|
6
|
+
class Server < EventMachine::Connection
|
7
|
+
attr_accessor :options, :status
|
8
|
+
|
9
|
+
def receive_data(data)
|
10
|
+
puts "#{@status} -- #{data}"
|
11
|
+
send_data("helo\n")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
EM.run do
|
16
|
+
EM.start_server 'localhost', 8080, Server do |conn|
|
17
|
+
conn.options = {:my => 'options'}
|
18
|
+
conn.status = :OK
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'node.rb'
|
2
|
+
require 'provider.rb'
|
3
|
+
|
4
|
+
class ExecutionNode < Node
|
5
|
+
attr_accessor :execution_instance
|
6
|
+
def initialize (parent, block)
|
7
|
+
super(parent, block)
|
8
|
+
self.execution_instance = execution_instance
|
9
|
+
self.name = '[' + ExecutionNode.to_s + ']'
|
10
|
+
end
|
11
|
+
|
12
|
+
def draw_block(graph)
|
13
|
+
graph.rect << graph.node(id)
|
14
|
+
graph.node(id).label(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def run(instance)
|
18
|
+
totalTime =
|
19
|
+
{
|
20
|
+
:name => self.name,
|
21
|
+
:total => 0,
|
22
|
+
:before => 0,
|
23
|
+
:exec => {},
|
24
|
+
:after => 0
|
25
|
+
}
|
26
|
+
|
27
|
+
start = Time.now
|
28
|
+
|
29
|
+
commands.each_with_index do |command, index|
|
30
|
+
_start = Time.now
|
31
|
+
if instance.nil?
|
32
|
+
puts `#{command}`
|
33
|
+
else
|
34
|
+
$virtual_machines[instance].invoke [[command]]
|
35
|
+
end
|
36
|
+
_finish = Time.now
|
37
|
+
totalTime[:exec]["#{index}. " + command] = _finish - _start
|
38
|
+
end
|
39
|
+
finish = Time.now
|
40
|
+
|
41
|
+
totalTime[:total] = finish - start
|
42
|
+
return totalTime
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'graph.rb'
|
2
|
+
require 'awesome_print'
|
3
|
+
|
4
|
+
class Node
|
5
|
+
attr_accessor :parent, :code_block, :is_safely, :node_list,
|
6
|
+
:before_list, :after_list, :is_asynchronously,
|
7
|
+
:exec_block, :commands, :name, :id
|
8
|
+
|
9
|
+
def initialize(parent, block)
|
10
|
+
self.parent = parent
|
11
|
+
self.code_block = block
|
12
|
+
self.node_list = Array.new
|
13
|
+
self.before_list = Array.new
|
14
|
+
self.after_list = Array.new
|
15
|
+
self.is_safely = false
|
16
|
+
self.is_asynchronously = false
|
17
|
+
self.commands = Array.new
|
18
|
+
self.id = self.to_s
|
19
|
+
self.name = '[Node]'
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(instance)
|
23
|
+
totalTime =
|
24
|
+
{
|
25
|
+
:name => self.name,
|
26
|
+
:before => 0,
|
27
|
+
:exec => [],
|
28
|
+
:after => 0
|
29
|
+
}
|
30
|
+
|
31
|
+
start = Time.now
|
32
|
+
before_list.each do |before_command|
|
33
|
+
if instance.nil?
|
34
|
+
puts `#{before_command}`
|
35
|
+
else
|
36
|
+
$virtual_machines[instance].invoke [[before_command]]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
finish = Time.now
|
40
|
+
|
41
|
+
totalTime[:before] = finish - start
|
42
|
+
|
43
|
+
node_list.each do |node|
|
44
|
+
totalTime[:exec].push(node.run(instance))
|
45
|
+
end
|
46
|
+
|
47
|
+
start = Time.now
|
48
|
+
after_list.each do |after_command|
|
49
|
+
if instance.nil?
|
50
|
+
puts `#{after_command}`
|
51
|
+
else
|
52
|
+
$virtual_machines[instance].invoke [[after_command]]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
finish = Time.now
|
56
|
+
|
57
|
+
totalTime[:after] = finish - start
|
58
|
+
|
59
|
+
return totalTime
|
60
|
+
end
|
61
|
+
|
62
|
+
def draw_block(graph)
|
63
|
+
graph.rect << graph.node(self.id)
|
64
|
+
graph.node(self.id).label(name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def draw_before_blocks(node, graph)
|
68
|
+
if node.before_list.length > 0
|
69
|
+
id = Random.rand(100000000000000000000000)
|
70
|
+
name = "[BEFORE]\n"
|
71
|
+
node.before_list.each do |before|
|
72
|
+
name += ">#{before}\n"
|
73
|
+
end
|
74
|
+
graph.rect << graph.node(id)
|
75
|
+
graph.green << graph.edge(node.id, id)
|
76
|
+
graph.node(id).label(name)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def draw_after_blocks(node, graph)
|
81
|
+
if node.after_list.length > 0
|
82
|
+
id = Random.rand(100000000000000000000000)
|
83
|
+
name = "[AFTER]\n"
|
84
|
+
node.after_list.each do |after|
|
85
|
+
name += ">#{after}\n"
|
86
|
+
end
|
87
|
+
graph.rect << graph.node(id)
|
88
|
+
graph.red << graph.edge(node.id, id)
|
89
|
+
graph.node(id).label(name)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def draw_child_nodes(node, graph)
|
94
|
+
node.node_list.each do |child_node|
|
95
|
+
child_node.commands.each do |command|
|
96
|
+
child_node.name += "\n >" +command.to_s
|
97
|
+
end
|
98
|
+
graph.edge(node.id, child_node.id)
|
99
|
+
paint(child_node, graph)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def paint(node, graph)
|
104
|
+
node.draw_block(graph)
|
105
|
+
draw_before_blocks(node, graph)
|
106
|
+
draw_child_nodes(node, graph)
|
107
|
+
draw_after_blocks(node, graph)
|
108
|
+
end
|
109
|
+
|
110
|
+
def print_tree
|
111
|
+
node = self
|
112
|
+
digraph do
|
113
|
+
node.paint(node, self)
|
114
|
+
save 'execution_graph', 'png'
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'node.rb'
|
2
|
+
|
3
|
+
class OnNode < Node
|
4
|
+
attr_accessor :instance
|
5
|
+
def initialize (parent, instance, block)
|
6
|
+
super(parent, block)
|
7
|
+
self.instance = instance
|
8
|
+
self.name = "[OnNode]\n" + instance
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(instance)
|
12
|
+
totalTime =
|
13
|
+
{
|
14
|
+
:name => self.name,
|
15
|
+
:before => 0,
|
16
|
+
:exec => [],
|
17
|
+
:after => 0
|
18
|
+
}
|
19
|
+
instance = @instance
|
20
|
+
|
21
|
+
start = Time.now
|
22
|
+
before_list.each do |before_command|
|
23
|
+
puts before_command
|
24
|
+
if instance.nil?
|
25
|
+
`#{before_command}`
|
26
|
+
else
|
27
|
+
$virtual_machines[instance].invoke [[before_command]]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
finish = Time.now
|
31
|
+
|
32
|
+
totalTime[:before] = finish - start
|
33
|
+
|
34
|
+
node_list.each do |node|
|
35
|
+
puts @instance
|
36
|
+
totalTime[:exec].push(node.run(@instance))
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
start = Time.now
|
41
|
+
after_list.each do |after_command|
|
42
|
+
if instance.nil?
|
43
|
+
`#{after_command}`
|
44
|
+
else
|
45
|
+
$virtual_machines[instance].invoke [[after_command]]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
finish = Time.now
|
49
|
+
|
50
|
+
totalTime[:after] = finish - start
|
51
|
+
|
52
|
+
return totalTime
|
53
|
+
end
|
54
|
+
|
55
|
+
def draw_block(graph)
|
56
|
+
graph.hexagon << graph.node(id)
|
57
|
+
graph.node(id).label(name)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'claudius'
|
2
|
+
|
3
|
+
config = load_config('./user_config.json')
|
4
|
+
|
5
|
+
experiment 'Montage' do
|
6
|
+
define_providers do
|
7
|
+
# cloud('aws', :provider => config['provider'],
|
8
|
+
# :region=>config['region'],
|
9
|
+
# :aws_access_key_id => config['aws_access_key_id'],
|
10
|
+
# :aws_secret_access_key => config['aws_secret_access_key'])
|
11
|
+
# .create_instances(['t1.micro'], 'ubuntu', './Piotr-key-pair-irleand.pem',
|
12
|
+
# :key_name => 'Piotr-key-pair-irleand',
|
13
|
+
# :groups => 'Piotr-irleand')
|
14
|
+
manual('kali', '172.16.0.104', 'root', :password => 'toor', :port => 22)
|
15
|
+
end
|
16
|
+
|
17
|
+
puts 'Prints once when tree is building'
|
18
|
+
before do
|
19
|
+
ssh "id"
|
20
|
+
end
|
21
|
+
after do
|
22
|
+
ssh "ls"
|
23
|
+
end
|
24
|
+
foreach ['kali', 'next'], asynchronously do |instance|
|
25
|
+
before do
|
26
|
+
ssh "who"
|
27
|
+
end
|
28
|
+
on instance do
|
29
|
+
before do
|
30
|
+
ssh "ps -aux"
|
31
|
+
end
|
32
|
+
after do
|
33
|
+
ssh "cat \"file.txt\""
|
34
|
+
end
|
35
|
+
|
36
|
+
concurrent do
|
37
|
+
execute do
|
38
|
+
i = 0
|
39
|
+
while (i < 2)
|
40
|
+
ssh "date"
|
41
|
+
i += 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
execute do
|
45
|
+
i = 2
|
46
|
+
while (i < 5)
|
47
|
+
ssh "ls"
|
48
|
+
i += 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
#$root.run(0, nil)
|
56
|
+
#$root.print_tree
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'claudius'
|
2
|
+
config = load_config('./user_config.json')
|
3
|
+
experiment 'Montage' do
|
4
|
+
define_providers do
|
5
|
+
cloud('aws', :provider => config['provider'],
|
6
|
+
:region =>config['region'],
|
7
|
+
:endpoint => 'https://ec2.eu-west-1.amazonaws.com/',
|
8
|
+
:aws_access_key_id => config['aws_access_key_id'],
|
9
|
+
:aws_secret_access_key => config['aws_secret_access_key'])
|
10
|
+
.create_instances(['t1.micro=>in1'],
|
11
|
+
:username => 'ubuntu',
|
12
|
+
:private_key_path =>'./Piotr-key-pair-irleand.pem',
|
13
|
+
:key_name => 'Piotr-key-pair-irleand',
|
14
|
+
:groups => ['Piotr-irleand'])
|
15
|
+
manual('kali', '172.16.0.101', 'root', :password => 'toor', :port => 22)
|
16
|
+
end
|
17
|
+
|
18
|
+
foreach ['kali','in1'] do |instance|
|
19
|
+
before do
|
20
|
+
ssh "who"
|
21
|
+
end
|
22
|
+
foreach ['a', 'b', 'c'] do |param|
|
23
|
+
before do
|
24
|
+
ssh "who"
|
25
|
+
end
|
26
|
+
on instance do
|
27
|
+
concurrent do
|
28
|
+
execute do
|
29
|
+
ssh "cd ~/Desktop; mkdir test2323"
|
30
|
+
end
|
31
|
+
execute do
|
32
|
+
ssh "echo #{param}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/test/test.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'claudius'
|
2
|
+
require "awesome_print"
|
3
|
+
|
4
|
+
experiment_tree = experiment 'sdsdf' do
|
5
|
+
define_providers do
|
6
|
+
# cloud('aws', :provider => config['provider'],
|
7
|
+
# :region=>config['region'],
|
8
|
+
# :aws_access_key_id => config['aws_access_key_id'],
|
9
|
+
# :aws_secret_access_key => config['aws_secret_access_key'])
|
10
|
+
# .create_instances(['t1.micro'], 'ubuntu', './Piotr-key-pair-irleand.pem',
|
11
|
+
# :key_name => 'Piotr-key-pair-irleand',
|
12
|
+
# :groups => 'Piotr-irleand')
|
13
|
+
manual('kali', '192.168.1.116', 'root', :password => 'toor', :port => 22)
|
14
|
+
end
|
15
|
+
|
16
|
+
foreach ['kali'] do |instance|
|
17
|
+
foreach ['a'] do |param|
|
18
|
+
before do
|
19
|
+
end
|
20
|
+
on instance do
|
21
|
+
execute 'install prerequisites' do
|
22
|
+
ssh "curl -O http://pegasus.isi.edu/montage/Montage_v3.3_patched_4.tar.gz"
|
23
|
+
ssh "tar zxvf Montage_v3.3_patched_4.tar.gz"
|
24
|
+
ssh "cd Montage_v3.3_patched_4"
|
25
|
+
ssh "make"
|
26
|
+
ssh "cd .."
|
27
|
+
ssh "git clone https://github.com/dice-cyfronet/hyperflow.git --depth 1 -b develop"
|
28
|
+
ssh "cd hyperflow"
|
29
|
+
ssh "npm install"
|
30
|
+
ssh "curl -O https://dl.dropboxusercontent.com/u/81819/hyperflow-amqp-executor.gem"
|
31
|
+
ssh "echo toor | sudo -S gem2.0 install --no-ri --no-rdoc hyperflow-amqp-executor.gem"
|
32
|
+
end
|
33
|
+
execute do
|
34
|
+
ssh "date"
|
35
|
+
end
|
36
|
+
execute do
|
37
|
+
ssh "echo #{param}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
after do
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
experiment_tree.run_with_time
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'claudius'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class Test_local_execution < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def teardown
|
7
|
+
`rm -rf Hello123456`
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_simple
|
11
|
+
experiment 'Hello' do
|
12
|
+
execute do
|
13
|
+
ssh 'mkdir Hello123456'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
result = `ls -la`
|
17
|
+
assert_equal(true, result.include?('Hello123456'), 'Test should create a folder in current directory')
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: claudius
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- radk0s
|
9
|
+
- blost
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2014-06-05 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bundler
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '1.3'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '1.3'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: rake
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
type: :development
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: fog
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: net-ssh
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: graph
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
type: :runtime
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
description: Write a gem description
|
96
|
+
email:
|
97
|
+
- rachamot@gmail.com
|
98
|
+
executables: []
|
99
|
+
extensions: []
|
100
|
+
extra_rdoc_files: []
|
101
|
+
files:
|
102
|
+
- .gitignore
|
103
|
+
- Gemfile
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- claudius.gemspec
|
108
|
+
- examples/_
|
109
|
+
- examples/on_instance.rb
|
110
|
+
- examples/simple_program.rb
|
111
|
+
- examples/specify_instances.rb
|
112
|
+
- lib/remote_execution/cloud_provider.rb
|
113
|
+
- lib/remote_execution/provider.rb
|
114
|
+
- lib/remote_execution/virtual_machine.rb
|
115
|
+
- lib/tree_building/claudius.rb
|
116
|
+
- lib/tree_building/concurrent_node.rb
|
117
|
+
- lib/tree_building/event_machine_play.rb
|
118
|
+
- lib/tree_building/execution_node.rb
|
119
|
+
- lib/tree_building/node.rb
|
120
|
+
- lib/tree_building/on_node.rb
|
121
|
+
- test/execution_test.rb
|
122
|
+
- test/gem_usage_test.rb
|
123
|
+
- test/test.rb
|
124
|
+
- test/test_local_execution.rb
|
125
|
+
homepage: https://github.com/blostic/claudius
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib/tree_building
|
132
|
+
- lib/remote_execution
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ! '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
|
+
none: false
|
141
|
+
requirements:
|
142
|
+
- - ! '>='
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
requirements: []
|
146
|
+
rubyforge_project:
|
147
|
+
rubygems_version: 1.8.23
|
148
|
+
signing_key:
|
149
|
+
specification_version: 3
|
150
|
+
summary: Write a gem summary
|
151
|
+
test_files:
|
152
|
+
- test/execution_test.rb
|
153
|
+
- test/gem_usage_test.rb
|
154
|
+
- test/test.rb
|
155
|
+
- test/test_local_execution.rb
|