nitos_testbed_rc 1.0.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ #this resource is used to control applications frisbee/frisbeed and imagezip_server/imagezip_client.
2
+
3
+ $ports = []
4
+ module OmfRc::ResourceProxy::FrisbeeFactory
5
+ include OmfRc::ResourceProxyDSL
6
+
7
+ @config = YAML.load_file('/etc/nitos_testbed_rc/frisbee_proxy_conf.yaml')
8
+ # @config = YAML.load_file(File.join(File.dirname(File.expand_path(__FILE__)), '../etc/frisbee_proxy_conf.yaml'))
9
+ @fconf = @config[:frisbee]
10
+
11
+ register_proxy :frisbee_factory
12
+
13
+ request :ports do |res|
14
+ port = @fconf[:startPort]
15
+ loop do
16
+ if $ports.include?(port)
17
+ port +=1
18
+ elsif !res.port_open?(port)
19
+ port +=1
20
+ else
21
+ $ports << port
22
+ break
23
+ end
24
+ end
25
+ debug "port chosen: '#{port}'"
26
+ port
27
+ end
28
+
29
+ def port_open?(port, seconds=1)
30
+ Timeout::timeout(seconds) do
31
+ begin
32
+ TCPServer.new('localhost', port) rescue return false
33
+ return true
34
+ end
35
+ end
36
+ rescue Timeout::Error
37
+ return false
38
+ end
39
+ end
@@ -0,0 +1,98 @@
1
+ #frisbee server
2
+ #created by parent :frisbee_factory
3
+ #used in load command
4
+
5
+ module OmfRc::ResourceProxy::Frisbeed
6
+ include OmfRc::ResourceProxyDSL
7
+ require 'omf_common/exec_app'
8
+
9
+ @config = YAML.load_file('/etc/nitos_testbed_rc/frisbee_proxy_conf.yaml')
10
+ # @config = YAML.load_file(File.join(File.dirname(File.expand_path(__FILE__)), '../etc/frisbee_proxy_conf.yaml'))
11
+ @fconf = @config[:frisbee]
12
+
13
+ register_proxy :frisbeed, :create_by => :frisbee_factory
14
+
15
+ utility :common_tools
16
+ utility :platform_tools
17
+
18
+ property :app_id, :default => nil
19
+ property :binary_path, :default => @fconf[:frisbeedBin] #binary path to frisbeed '/usr/sbin/frisbeed'
20
+ property :map_err_to_out, :default => false
21
+
22
+ property :multicast_interface, :default => @fconf[:multicastIF] #multicast interface, example 10.0.0.200 (-i arguement)
23
+ property :multicast_address, :default => @fconf[:mcAddress] #multicast address, example 224.0.0.1 (-m arguement)
24
+ property :port #port, example 7000 (-p arguement)
25
+ property :speed, :default => @fconf[:bandwidth] #bandwidth speed in bits/sec, example 50000000 (-W arguement)
26
+ property :image, :default => @fconf[:imageDir] + '/' + @fconf[:defaultImage] #image to burn, example /var/lib/omf-images-5.4/baseline.ndz
27
+
28
+
29
+
30
+ hook :after_initial_configured do |server|
31
+ server.property.app_id = server.hrn.nil? ? server.uid : server.hrn
32
+ server.property.image = server.property.image.nil? ? @fconf[:imageDir] + '/' + @fconf[:defaultImage] : server.property.image
33
+ server.property.image = server.property.image.start_with?('/') ? server.property.image : @fconf[:imageDir] + '/' + server.property.image
34
+ unless File.file?(server.property.image)
35
+ debug "File '#{server.property.image}' does not exist."
36
+ raise "FILE NOT FOUND."
37
+ end
38
+ debug "Frisbee server is loading image: #{server.property.image}"
39
+
40
+ @app = ExecApp.new(server.property.app_id, server.build_command_line, server.property.map_err_to_out) do |event_type, app_id, msg|
41
+ server.process_event(server, event_type, app_id, msg)
42
+ end
43
+ end
44
+
45
+ hook :before_release do |server|
46
+ begin
47
+ @app.signal(signal = 'KILL')
48
+ rescue Exception => e
49
+ raise e unless e.message == "No such process"
50
+ ensure
51
+ $ports.delete_if {|x| x == server.property.port}
52
+ end
53
+ end
54
+
55
+ # This method processes an event coming from the application instance, which
56
+ # was started by this Resource Proxy (RP). It is a callback, which is usually
57
+ # called by the ExecApp class in OMF
58
+ #
59
+ # @param [AbstractResource] res this RP
60
+ # @param [String] event_type the type of event from the app instance
61
+ # (STARTED, DONE.OK, DONE.ERROR, STDOUT, STDERR)
62
+ # @param [String] app_id the id of the app instance
63
+ # @param [String] msg the message carried by the event
64
+ #
65
+ def process_event(res, event_type, app_id, msg)
66
+ logger.info "Frisbeed: App Event from '#{app_id}' - #{event_type}: '#{msg}'"
67
+ if event_type == 'EXIT' #maybe i should inform you for every event_type.
68
+ res.inform(:status, {
69
+ status_type: 'FRISBEED',
70
+ event: event_type.to_s.upcase,
71
+ app: app_id,
72
+ exit_code: msg,
73
+ msg: msg
74
+ }, :ALL)
75
+ elsif event_type == 'STDOUT'
76
+ res.inform(:status, {
77
+ status_type: 'FRISBEED',
78
+ event: event_type.to_s.upcase,
79
+ app: app_id,
80
+ exit_code: msg,
81
+ msg: msg
82
+ }, :ALL)
83
+ end
84
+ end
85
+
86
+ # Build the command line, which will be used to add a new user.
87
+ #
88
+ work('build_command_line') do |res|
89
+ cmd_line = "env -i " # Start with a 'clean' environment
90
+ cmd_line += res.property.binary_path + " " # the /usr/sbin/frisbeed
91
+ cmd_line += "-i " + res.property.multicast_interface + " " # -i for interface
92
+ cmd_line += "-m " + res.property.multicast_address + " " # -m for address
93
+ cmd_line += "-p " + res.property.port.to_s + " " # -p for port
94
+ cmd_line += "-W " + res.property.speed.to_s + " " # -W for bandwidth
95
+ cmd_line += res.property.image # image no arguement
96
+ cmd_line
97
+ end
98
+ end
@@ -0,0 +1,84 @@
1
+ #Imagezip client
2
+ #created by parent :frisbee_factory
3
+ #used in save command
4
+
5
+ #$domain = @config[:domain][:ip]
6
+
7
+ module OmfRc::ResourceProxy::ImagezipClient #Imagezip client
8
+ include OmfRc::ResourceProxyDSL
9
+ require 'omf_common/exec_app'
10
+
11
+ @config = YAML.load_file('/etc/nitos_testbed_rc/frisbee_proxy_conf.yaml')
12
+ # @config = YAML.load_file(File.join(File.dirname(File.expand_path(__FILE__)), '../etc/frisbee_proxy_conf.yaml'))
13
+ @fconf = @config[:frisbee]
14
+
15
+ register_proxy :imagezip_client, :create_by => :frisbee_factory
16
+
17
+ utility :common_tools
18
+ utility :platform_tools
19
+
20
+ property :app_id, :default => nil
21
+ property :binary_path, :default => @fconf[:imagezipClientBin] #usually '/usr/bin/imagezip'
22
+ property :map_err_to_out, :default => false
23
+
24
+ property :ip, :default => @fconf[:multicastIF]
25
+ property :port
26
+ property :hardrive, :default => "/dev/sda"
27
+ property :node_topic
28
+
29
+ hook :after_initial_configured do |client|
30
+ Thread.new do
31
+ debug "Received message '#{client.opts.inspect}'"
32
+ if error_msg = client.opts.error_msg
33
+ res.inform(:error,{
34
+ event_type: "AUTH",
35
+ exit_code: "-1",
36
+ node_name: client.property.node_topic,
37
+ msg: error_msg
38
+ }, :ALL)
39
+ next
40
+ end
41
+
42
+ nod = {}
43
+ nod[:node_name] = client.opts.node.resource.name
44
+ client.opts.node.resource.interfaces.each do |i|
45
+ if i[:role] == "control"
46
+ nod[:node_ip] = i[:ip][:address]
47
+ nod[:node_mac] = i[:mac]
48
+ elsif i[:role] == "cm_network"
49
+ nod[:node_cm_ip] = i[:ip][:address]
50
+ end
51
+ end
52
+ nod[:node_cm_ip] = client.opts.node.resource.cmc.ip.address
53
+
54
+ client.property.app_id = client.hrn.nil? ? client.uid : client.hrn
55
+
56
+ command = "#{client.property.binary_path} -o -z1 #{client.property.hardrive} - | /bin/nc -q 0 #{client.property.ip} #{client.property.port}"
57
+ debug "Executing command #{command}"
58
+ # nod = {node_name: "node1", node_ip: "10.0.0.1", node_mac: "00-03-1d-0d-4b-96", node_cm_ip: "10.0.0.101"}
59
+
60
+ host = Net::Telnet.new("Host" => nod[:node_ip], "Timeout" => false)#, "Prompt" => /[\w().-]*[\$#>:.]\s?(?:\(enable\))?\s*$/)
61
+ host.cmd(command.to_s) do |c|
62
+ if c.to_s != "\n" && c[0,5] != "\n/usr" && c.to_s != "." && c.to_s != ".." && c.to_s != "..."
63
+ #puts '__' + c.to_s + '__'
64
+ client.inform(:status, {
65
+ status_type: 'IMAGEZIP',
66
+ event: "STDOUT",
67
+ app: client.property.app_id,
68
+ node: client.property.node_topic,
69
+ msg: "#{c.to_s}"
70
+ }, :ALL)
71
+ end
72
+ end
73
+
74
+ client.inform(:status, {
75
+ status_type: 'IMAGEZIP',
76
+ event: "EXIT",
77
+ app: client.property.app_id,
78
+ node: client.property.node_topic,
79
+ msg: 'imagezip client completed.'
80
+ }, :ALL)
81
+ host.close
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,65 @@
1
+ #Imagezip client
2
+ #created by parent :frisbee_factory
3
+ #used in save command
4
+
5
+ module OmfRc::ResourceProxy::ImagezipServer #Imagezip server
6
+ include OmfRc::ResourceProxyDSL
7
+ require 'omf_common/exec_app'
8
+
9
+ @config = YAML.load_file('/etc/nitos_testbed_rc/frisbee_proxy_conf.yaml')
10
+ # @config = YAML.load_file(File.join(File.dirname(File.expand_path(__FILE__)), '../etc/frisbee_proxy_conf.yaml'))
11
+ @fconf = @config[:frisbee]
12
+
13
+ register_proxy :imagezip_server, :create_by => :frisbee_factory
14
+
15
+ utility :common_tools
16
+ utility :platform_tools
17
+
18
+ property :app_id, :default => nil
19
+ property :binary_path, :default => @fconf[:imagezipServerBin] #usualy '/bin/nc'
20
+ property :map_err_to_out, :default => false
21
+
22
+ property :ip, :default => @fconf[:multicastIF]
23
+ property :port
24
+ property :image_name, :default => @fconf[:imageDir] + '/new_image.ndz'
25
+
26
+ hook :after_initial_configured do |server|
27
+ server.property.app_id = server.hrn.nil? ? server.uid : server.hrn
28
+
29
+ @app = ExecApp.new(server.property.app_id, server.build_command_line, server.property.map_err_to_out) do |event_type, app_id, msg|
30
+ server.process_event(server, event_type, app_id, msg)
31
+ end
32
+ end
33
+
34
+ hook :before_release do |server|
35
+ $ports.delete_if {|x| x == server.property.port} #ports is in frisbee_factory
36
+ end
37
+
38
+ def process_event(res, event_type, app_id, msg)
39
+ logger.info "Frisbeed: App Event from '#{app_id}' - #{event_type}: '#{msg}'"
40
+ if event_type == 'EXIT' #maybe i should inform you for every event_type, we'll see.
41
+ res.inform(:status, {
42
+ status_type: 'IMAGEZIP',
43
+ event: event_type.to_s.upcase,
44
+ app: app_id,
45
+ exit_code: msg,
46
+ msg: msg
47
+ }, :ALL)
48
+ elsif event_type == 'STDOUT'
49
+ res.inform(:status, {
50
+ status_type: 'IMAGEZIP',
51
+ event: event_type.to_s.upcase,
52
+ app: app_id,
53
+ exit_code: msg,
54
+ msg: msg
55
+ }, :ALL)
56
+ end
57
+ end
58
+
59
+ work('build_command_line') do |res|
60
+ cmd_line = "env -i " # Start with a 'clean' environment
61
+ cmd_line += res.property.binary_path + " "
62
+ cmd_line += "-d -l " + res.property.ip + " " + res.property.port.to_s + " > " + res.property.image_name
63
+ cmd_line
64
+ end
65
+ end
@@ -0,0 +1,133 @@
1
+ #This resource is created the parent :user_factory resource
2
+
3
+
4
+ module OmfRc::ResourceProxy::User
5
+ include OmfRc::ResourceProxyDSL
6
+
7
+ require 'omf_common/exec_app'
8
+
9
+ register_proxy :user, :create_by => :user_factory
10
+
11
+ utility :common_tools
12
+ utility :platform_tools
13
+
14
+ property :username
15
+ property :app_id, :default => nil
16
+ property :binary_path, :default => '/usr/sbin/useradd'
17
+ property :map_err_to_out, :default => false
18
+
19
+ configure :cert do |res, value|
20
+ #puts "CERTIFICATE #{value.inspect}"
21
+ path = "/home/#{res.property.username}/.omf/"
22
+ unless File.directory?(path)#create the directory if it doesn't exist (it will never exist)
23
+ FileUtils.mkdir_p(path)
24
+ end
25
+
26
+ File.write("#{path}/cert.pem", value)
27
+ end
28
+
29
+ configure :auth_keys do |res, value|
30
+ File.open("/home/#{res.property.username}/.ssh/authorized_keys", 'w') do |file|
31
+ value.each do |v|
32
+ file.puts v
33
+ end
34
+ end
35
+ end
36
+
37
+ #hook :before_ready do |user|
38
+ #define_method("on_app_event") { |*args| process_event(self, *args) }
39
+ #end
40
+
41
+ hook :after_initial_configured do |user|
42
+ user.property.app_id = user.hrn.nil? ? user.uid : user.hrn
43
+
44
+ ExecApp.new(user.property.app_id, user.build_command_line, user.property.map_err_to_out) do |event_type, app_id, msg|
45
+ user.process_event(user, event_type, app_id, msg)
46
+ end
47
+ end
48
+
49
+ # This method processes an event coming from the application instance, which
50
+ # was started by this Resource Proxy (RP). It is a callback, which is usually
51
+ # called by the ExecApp class in OMF
52
+ #
53
+ # @param [AbstractResource] res this RP
54
+ # @param [String] event_type the type of event from the app instance
55
+ # (STARTED, DONE.OK, DONE.ERROR, STDOUT, STDERR)
56
+ # @param [String] app_id the id of the app instance
57
+ # @param [String] msg the message carried by the event
58
+ #
59
+ def process_event(res, event_type, app_id, msg)
60
+ logger.info "App Event from '#{app_id}' - #{event_type}: '#{msg}'"
61
+ if event_type == 'EXIT'
62
+ if msg == 0 #only when user creation succeeds, create a new public key and save it to /home/username/.ssh/
63
+ #then inform with the appropriate msg, and give the pub key
64
+ key = OpenSSL::PKey::RSA.new(2048)
65
+
66
+ pub_key = key.public_key
67
+
68
+ path = "/home/#{res.property.username}/.ssh/"
69
+ unless File.directory?(path)#create the directory if it doesn't exist (it will never exist)
70
+ FileUtils.mkdir_p(path)
71
+ end
72
+
73
+ File.write("#{path}/pub_key.pem", pub_key.to_pem)
74
+ File.write("#{path}/key.pem", key.to_pem)
75
+
76
+ res.inform(:status, {
77
+ status_type: 'APP_EVENT',
78
+ event: event_type.to_s.upcase,
79
+ app: app_id,
80
+ exit_code: msg,
81
+ msg: msg,
82
+ uid: res.uid, # do we really need this? Should be identical to 'src'
83
+ pub_key: pub_key
84
+ }, :ALL)
85
+ else #if msg!=0 then the application failed to complete
86
+ path = "/home/#{res.property.username}/.ssh/"
87
+ if File.exists?("#{path}/pub_key.pem") && File.exists?("#{path}/key.pem")#if keys exist just read the pub_key for the inform
88
+ file = File.open("#{path}/pub_key.pem", "rb")
89
+ pub_key = file.read
90
+ file.close
91
+ else #if keys do not exist create them and then inform
92
+ key = OpenSSL::PKey::RSA.new(2048)
93
+
94
+ pub_key = key.public_key
95
+
96
+ path = "/home/#{res.property.username}/.ssh/"
97
+ unless File.directory?(path)#create the directory if it doesn't exist (it will never exist)
98
+ FileUtils.mkdir_p(path)
99
+ end
100
+
101
+ File.write("#{path}/pub_key.pem", pub_key.to_pem)
102
+ File.write("#{path}/key.pem", key.to_pem)
103
+ end
104
+ res.inform(:status, {
105
+ status_type: 'APP_EVENT',
106
+ event: event_type.to_s.upcase,
107
+ app: app_id,
108
+ exit_code: msg,
109
+ msg: msg,
110
+ uid: res.uid, # do we really need this? Should be identical to 'src'
111
+ pub_key: pub_key
112
+ }, :ALL)
113
+ end
114
+ else
115
+ res.inform(:status, {
116
+ status_type: 'APP_EVENT',
117
+ event: event_type.to_s.upcase,
118
+ app: app_id,
119
+ msg: msg,
120
+ uid: res.uid
121
+ }, :ALL)
122
+ end
123
+ end
124
+
125
+ # Build the command line, which will be used to add a new user.
126
+ #
127
+ work('build_command_line') do |res|
128
+ cmd_line = "env -i " # Start with a 'clean' environment
129
+ cmd_line += res.property.binary_path + " " # the /usr/sbin/useradd
130
+ cmd_line += " -m -s /bin/bash #{res.property.username}" # the username, -m for adding folder -s for default shell to /bin/bash, removed -d /home/#{res.property.username}
131
+ cmd_line
132
+ end
133
+ end
@@ -0,0 +1,13 @@
1
+ #This resource is related with user instance
2
+
3
+
4
+ module OmfRc::ResourceProxy::UserFactory
5
+ include OmfRc::ResourceProxyDSL
6
+
7
+ register_proxy :user_factory
8
+
9
+ configure :deluser do |res, value|
10
+ cmd = 'userdel -r ' + value[:username]
11
+ system cmd
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ module Nitos
2
+ module TestbedRc
3
+ end
4
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ module NITOS
2
+ module TestbedRc
3
+ VERSION = "1.0.0.pre.1"
4
+ end
5
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "version.rb"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nitos_testbed_rc"
7
+ s.version = NITOS::TestbedRc::VERSION
8
+ s.authors = ["NITOS"]
9
+ s.email = ["nitlab@inf.uth.gr"]
10
+ s.homepage = "http://nitlab.inf.uth.gr"
11
+ s.summary = %q{NITOS testbed resource controllers.}
12
+ s.description = %q{NITOS testbed resource controllers that support a. Chassis manager cards, b. frisbee clients and servers for loading and saving images and c. user creation.}
13
+
14
+ s.rubyforge_project = "nitos_testbed_rc"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ # s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_runtime_dependency "omf_common", "~> 6.1.2.pre.5"
23
+ s.add_runtime_dependency "omf_rc", "~> 6.1.2.pre.5"
24
+ s.add_runtime_dependency "nokogiri", "~> 1.6.0"
25
+ s.add_development_dependency "net-ssh", "~> 2.8.0"
26
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nitos_testbed_rc
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.pre.1
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - NITOS
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-06-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: omf_common
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 6.1.2.pre.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 6.1.2.pre.5
30
+ - !ruby/object:Gem::Dependency
31
+ name: omf_rc
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 6.1.2.pre.5
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 6.1.2.pre.5
46
+ - !ruby/object:Gem::Dependency
47
+ name: nokogiri
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.6.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.6.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: net-ssh
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 2.8.0
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 2.8.0
78
+ description: NITOS testbed resource controllers that support a. Chassis manager cards,
79
+ b. frisbee clients and servers for loading and saving images and c. user creation.
80
+ email:
81
+ - nitlab@inf.uth.gr
82
+ executables:
83
+ - cm_proxy
84
+ - frisbee_proxy
85
+ - install_ntrc
86
+ - omf6
87
+ - run_proxies
88
+ - user_proxy
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - .gitignore
93
+ - README.md
94
+ - bin/cm_proxy
95
+ - bin/frisbee_proxy
96
+ - bin/install_ntrc
97
+ - bin/omf6
98
+ - bin/run_proxies
99
+ - bin/user_proxy
100
+ - etc/cm_proxy_conf.yaml
101
+ - etc/frisbee_proxy_conf.yaml
102
+ - etc/omf_script_conf.yaml
103
+ - etc/user_proxy_conf.yaml
104
+ - lib/nitos_testbed_rc.rb
105
+ - lib/nitos_testbed_rc/cm_factory.rb
106
+ - lib/nitos_testbed_rc/frisbee.rb
107
+ - lib/nitos_testbed_rc/frisbee_factory.rb
108
+ - lib/nitos_testbed_rc/frisbeed.rb
109
+ - lib/nitos_testbed_rc/imagezip_client.rb
110
+ - lib/nitos_testbed_rc/imagezip_server.rb
111
+ - lib/nitos_testbed_rc/user.rb
112
+ - lib/nitos_testbed_rc/user_factory.rb
113
+ - lib/version.rb
114
+ - nitos_testbed_rc.gemspec
115
+ homepage: http://nitlab.inf.uth.gr
116
+ licenses: []
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ! '>'
131
+ - !ruby/object:Gem::Version
132
+ version: 1.3.1
133
+ requirements: []
134
+ rubyforge_project: nitos_testbed_rc
135
+ rubygems_version: 1.8.25
136
+ signing_key:
137
+ specification_version: 3
138
+ summary: NITOS testbed resource controllers.
139
+ test_files: []