nifty 0.0.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +79 -12
  3. data/bin/nifty +2 -0
  4. data/config/nifty.yml +18 -0
  5. data/config/templates/image.erb +38 -0
  6. data/config/templates/template.erb +26 -0
  7. data/lib/nifty/backend.rb +55 -0
  8. data/lib/nifty/backends/opennebula.rb +109 -0
  9. data/lib/nifty/backends/utils/opennebula/datastore_handler.rb +36 -0
  10. data/lib/nifty/backends/utils/opennebula/group_handler.rb +23 -0
  11. data/lib/nifty/backends/utils/opennebula/handler.rb +60 -0
  12. data/lib/nifty/backends/utils/opennebula/helper.rb +44 -0
  13. data/lib/nifty/backends/utils/opennebula/image_handler.rb +209 -0
  14. data/lib/nifty/backends/utils/opennebula/template_handler.rb +91 -0
  15. data/lib/nifty/backends/utils/opennebula.rb +9 -0
  16. data/lib/nifty/backends/utils.rb +2 -0
  17. data/lib/nifty/backends.rb +5 -0
  18. data/lib/nifty/command_executioner.rb +202 -0
  19. data/lib/nifty/errors/api_call_timeout_error.rb +1 -0
  20. data/lib/nifty/errors/argument_error.rb +1 -0
  21. data/lib/nifty/errors/backend_error.rb +1 -0
  22. data/lib/nifty/errors/backends/opennebula/authentication_error.rb +1 -0
  23. data/lib/nifty/errors/backends/opennebula/resource_not_found_error.rb +1 -0
  24. data/lib/nifty/errors/backends/opennebula/resource_retrieval_error.rb +1 -0
  25. data/lib/nifty/errors/backends/opennebula/resource_state_error.rb +1 -0
  26. data/lib/nifty/errors/backends/opennebula/stub_error.rb +1 -0
  27. data/lib/nifty/errors/backends/opennebula/user_not_authorized_error.rb +1 -0
  28. data/lib/nifty/errors/backends/opennebula.rb +5 -0
  29. data/lib/nifty/errors/backends/opennebula_error.rb +1 -0
  30. data/lib/nifty/errors/backends.rb +4 -0
  31. data/lib/nifty/errors/command_execution_error.rb +1 -0
  32. data/lib/nifty/errors/event/converter_error.rb +1 -0
  33. data/lib/nifty/errors/event/loader_error.rb +1 -0
  34. data/lib/nifty/errors/event.rb +5 -0
  35. data/lib/nifty/errors/events/event_error.rb +1 -0
  36. data/lib/nifty/errors/events/expiration_event_error.rb +1 -0
  37. data/lib/nifty/errors/events/registration_event_error.rb +1 -0
  38. data/lib/nifty/errors/events.rb +4 -0
  39. data/lib/nifty/errors/standard_error.rb +1 -0
  40. data/lib/nifty/errors/transfer_method_error.rb +1 -0
  41. data/lib/nifty/errors/transfer_methods/destination_not_directory_error.rb +1 -0
  42. data/lib/nifty/errors/transfer_methods/destination_not_writable_error.rb +1 -0
  43. data/lib/nifty/errors/transfer_methods/image_file_not_readable_error.rb +1 -0
  44. data/lib/nifty/errors/transfer_methods.rb +4 -0
  45. data/lib/nifty/errors.rb +10 -0
  46. data/lib/nifty/event/converter.rb +29 -0
  47. data/lib/nifty/event/loader.rb +27 -0
  48. data/lib/nifty/event/processor.rb +96 -0
  49. data/lib/nifty/event.rb +6 -0
  50. data/lib/nifty/events/event.rb +32 -0
  51. data/lib/nifty/events/opennebula/event.rb +23 -0
  52. data/lib/nifty/events/opennebula/expiration_event.rb +32 -0
  53. data/lib/nifty/events/opennebula/metadata_update_event.rb +12 -0
  54. data/lib/nifty/events/opennebula/registration_event.rb +113 -0
  55. data/lib/nifty/events/opennebula/utils/events_common.rb +69 -0
  56. data/lib/nifty/events/opennebula/utils.rb +4 -0
  57. data/lib/nifty/events/opennebula.rb +6 -0
  58. data/lib/nifty/events.rb +5 -0
  59. data/lib/nifty/exit_codes.rb +8 -0
  60. data/lib/nifty/settings.rb +18 -0
  61. data/lib/nifty/transfer_method.rb +69 -0
  62. data/lib/nifty/transfer_methods/opennebula/cp.rb +52 -0
  63. data/lib/nifty/transfer_methods/opennebula/noop.rb +27 -0
  64. data/lib/nifty/transfer_methods/opennebula.rb +4 -0
  65. data/lib/nifty/transfer_methods.rb +4 -0
  66. data/lib/nifty/version.rb +1 -1
  67. data/lib/nifty.rb +20 -2
  68. data/nifty.gemspec +7 -0
  69. data/schema/appliance.json +295 -0
  70. data/templates/image.erb +8 -0
  71. data/templates/template.erb +13 -0
  72. metadata +166 -3
@@ -0,0 +1,209 @@
1
+ require 'timeout'
2
+ require 'erb'
3
+ require 'tilt/erb'
4
+
5
+ # Handler for OpenNebula ImagePool
6
+ #
7
+ # @author Michal Kimle
8
+ class Nifty::Backends::Utils::Opennebula::ImageHandler < Nifty::Backends::Utils::Opennebula::Handler
9
+
10
+ IMAGE_STATE_READY = 'READY'
11
+ IMAGE_STATE_DISABLED = 'DISABLED'
12
+ IMAGE_STATE_USED = 'USED'
13
+ IMAGE_STATE_ERROR = 'ERROR'
14
+ TIME_FORMAT = '%Y%m%d%H%M%S'
15
+ ATTRIBUTE_EXPIRATION = 'NIFTY_EXPIRATION'
16
+ ATTRIBUTE_OUTDATED = 'NIFTY_OUTDATED'
17
+ ATTRIBUTE_APPLIANCE_VERSION = 'NIFTY_APPLIANCE_VERSION'
18
+
19
+ # Constructor
20
+ #
21
+ # @see Nifty::Backends::Utils::Opennebula::Handler#initialize
22
+ def initialize(client)
23
+ super(client)
24
+ @pool = OpenNebula::ImagePool.new(client)
25
+ end
26
+
27
+ # Returns all images for given appliance id
28
+ #
29
+ # @param [String] appliance_id
30
+ # @return [Array] array of images
31
+ def images(appliance_id)
32
+ reload!
33
+
34
+ pool.find_all { |image| image["TEMPLATE/#{ATTRIBUTE_APPLIANCE_ID}"] == appliance_id }
35
+ end
36
+
37
+ # Returns all expired images (have attribute NIFTY_EXPIRATION)
38
+ #
39
+ # @return [Array] array of expired images
40
+ def expired_images()
41
+ reload!
42
+
43
+ pool.find_all { |image| image["TEMPLATE/#{ATTRIBUTE_EXPIRATION}"] }
44
+ end
45
+
46
+ def images_by_version(version)
47
+ reload!
48
+
49
+ pool.find_all { |image| image["TEMPLATE/#{ATTRIBUTE_APPLIANCE_VERSION}"] == version }
50
+ end
51
+
52
+ # Returns image with given id if exists
53
+ #
54
+ # @param [Fixnum] id
55
+ # @return [OpenNebula::Image] image with given id
56
+ def image_exist?(id)
57
+ reload!
58
+
59
+ pool.find { |image| image.id == id }
60
+ end
61
+
62
+ # Deletes image
63
+ #
64
+ # @param [OpenNebula::Image] image
65
+ # @raise [Nifty::Errors::ApiCallTimeoutError] if image isn't deleted within a timeout
66
+ def delete_image(image)
67
+ id = image.id
68
+
69
+ if image.state_str == IMAGE_STATE_USED
70
+ logger.warn("Image with id #{id.inspect} cannot be removed, still in use")
71
+ return
72
+ end
73
+
74
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.info! }
75
+ logger.debug("Deleting image with id #{id.inspect}")
76
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.delete }
77
+
78
+ Timeout::timeout(Nifty::API_CALL_TIMEOUT) do
79
+ while(image_exist?(id))
80
+ sleep(Nifty::API_POLLING_WAIT)
81
+ end
82
+ end
83
+ rescue Timeout::Error
84
+ fail Nifty::Errors::ApiCallTimeoutError, "Image with id #{id.inspect} was not deleted within timeout"
85
+ end
86
+
87
+ # Disables image
88
+ #
89
+ # @param [OpenNebula::Image] image
90
+ # @raise [Nifty::Errors::ApiCallTimeoutError] if image isn't disabled within a timeout
91
+ def disable_image(image)
92
+ image_state = image.state_str
93
+ id = image.id
94
+
95
+ if image_state == IMAGE_STATE_DISABLED
96
+ logger.debug("Image with id #{id.inspect} is already disabled, skipping")
97
+ return
98
+ end
99
+
100
+ unless image_state == IMAGE_STATE_READY || image_state == IMAGE_STATE_ERROR
101
+ logger.warn("Image with id #{id.inspect} cannot be disabled")
102
+ return
103
+ end
104
+
105
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.disable }
106
+
107
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.info! }
108
+ Timeout::timeout(Nifty::API_CALL_TIMEOUT) do
109
+ until(image.state_str == IMAGE_STATE_DISABLED)
110
+ sleep(Nifty::API_POLLING_WAIT)
111
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.info! }
112
+ end
113
+ end
114
+ end
115
+
116
+ # Expires image
117
+ # Renames image and add attribute NIFTY_EXPIRATION to image with timestamp as a value
118
+ #
119
+ # @param [OpenNebula::Image] image
120
+ def expire_image(image)
121
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.info! }
122
+ id = image.id
123
+
124
+ if image["TEMPLATE/#{ATTRIBUTE_EXPIRATION}"]
125
+ logger.debug("Image with id #{id.inspect} is already expired, skipping")
126
+ return
127
+ end
128
+
129
+ disable_image(image)
130
+
131
+ logger.debug("Expiring image with id #{id.inspect}")
132
+
133
+ expiration_time = Time.now.strftime(TIME_FORMAT)
134
+ expiration_attribute = "#{ATTRIBUTE_EXPIRATION} = \"#{expiration_time}\""
135
+
136
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.rename("EXPIRED_#{expiration_time}_#{image.name}") }
137
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.update(expiration_attribute, true) }
138
+ end
139
+
140
+ # Outdates image
141
+ # Adds atribute marking the image is outdated
142
+ #
143
+ # @param [OpenNebula::Image] image
144
+ def outdate_image(image)
145
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.info! }
146
+
147
+ id = image.id
148
+
149
+ if image["TEMPLATE/#{ATTRIBUTE_OUTDATED}"]
150
+ logger.debug("Image with id #{id.inspect} is already outdated, skipping")
151
+ return
152
+ end
153
+
154
+ logger.debug("Outdating image with id #{id.inspect}")
155
+
156
+ outdate_time = Time.now.strftime(TIME_FORMAT)
157
+ outdate_attribute = "#{ATTRIBUTE_OUTDATED} = \"#{outdate_time}\""
158
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.update(outdate_attribute, true) }
159
+ end
160
+
161
+ # Registers a new image
162
+ #
163
+ # @param [String] template template for image
164
+ # @param [OpenNebula::Datastore] datastore datastore to register image to
165
+ # @raise [Nifty::Errors::ApiCallTimeoutError] if image isn't ready within a timeout
166
+ def register_image(template, datastore)
167
+ image_alloc = ::OpenNebula::Image.build_xml
168
+ image = ::OpenNebula::Image.new(image_alloc, client)
169
+
170
+ logger.debug("Registering image with template\n#{template}")
171
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.allocate(template, datastore.id) }
172
+
173
+ begin
174
+ Timeout::timeout(Nifty::API_CALL_TIMEOUT) do
175
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.info! }
176
+
177
+ until(image.state_str == IMAGE_STATE_READY)
178
+ sleep(Nifty::API_POLLING_WAIT)
179
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { image.info! }
180
+ end
181
+ end
182
+
183
+ image
184
+ rescue Timeout::Error
185
+ image.delete
186
+ fail Nifty::Errors::ApiCallTimeoutError, "Image with id #{image.id.inspect} didn't become ready within timeout"
187
+ end
188
+ end
189
+
190
+ # Prepares a template for an image
191
+ #
192
+ # @param [String] template_dir directory with templates
193
+ # @param [Hash] data used while populating a template
194
+ # @return [String] final template for an image
195
+ def self.prepare_template(template_dir, data)
196
+ template_location = File.join(template_dir, "image.erb")
197
+ fail Nifty::Errors::ArgumentError, "Missing file 'image.erb' in template directory '#{template_dir}'" unless File.exist?(template_location)
198
+
199
+ template = Tilt::ERBTemplate.new(template_location)
200
+ template_content = template.render(Object.new, data)
201
+
202
+ template = Tilt::ERBTemplate.new(File.join(Nifty::GEM_DIR, 'templates', 'image.erb'))
203
+ nifty_template_content = template.render(Object.new, data)
204
+
205
+ whole_template_content = template_content + nifty_template_content
206
+ logger.debug "Populated image template:\n#{whole_template_content}"
207
+ whole_template_content
208
+ end
209
+ end
@@ -0,0 +1,91 @@
1
+ require 'timeout'
2
+ require 'erb'
3
+ require 'tilt/erb'
4
+ require 'set'
5
+
6
+ # Handler for OpenNebula TemplatePool
7
+ #
8
+ # @author Michal Kimle
9
+ class Nifty::Backends::Utils::Opennebula::TemplateHandler < Nifty::Backends::Utils::Opennebula::Handler
10
+
11
+ # Constructor
12
+ #
13
+ # @see Nifty::Backends::Utils::Opennebula::Handler#initialize
14
+ def initialize(client)
15
+ super(client)
16
+ @pool = OpenNebula::TemplatePool.new(client)
17
+ end
18
+
19
+ # Returns all templates for given appliance id
20
+ #
21
+ # @param [String] appliance_id
22
+ # @return [Array] array of templates
23
+ def templates(appliance_id)
24
+ reload!
25
+
26
+ pool.find_all{ |template| template["TEMPLATE/#{ATTRIBUTE_APPLIANCE_ID}"] == appliance_id }
27
+ end
28
+
29
+ # Returns template with given id if exists
30
+ #
31
+ # @param [Fixnum] id
32
+ # @return [OpenNebula::Template] template with given id
33
+ def template_exist?(id)
34
+ reload!
35
+
36
+ pool.find { |template| template.id == id }
37
+ end
38
+
39
+ # Deletes template
40
+ #
41
+ # @param [OpenNebula::Template] template
42
+ # @raise [Nifty::Errors::ApiCallTimeoutError] if template isn't deleted within a timeout
43
+ def delete_template(template)
44
+ template.info!
45
+ id = template.id
46
+
47
+ logger.debug("Deleting template with id #{id.inspect}")
48
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { template.delete }
49
+
50
+ Timeout::timeout(Nifty::API_CALL_TIMEOUT) do
51
+ while(template_exist?(id))
52
+ sleep(Nifty::API_POLLING_WAIT)
53
+ end
54
+ end
55
+ rescue Timeout::Error
56
+ fail Nifty::Errors::ApiCallTimeoutError, "Template with id #{template.id.inspect} was not deleted within timeout"
57
+ end
58
+
59
+ # Registers a new template
60
+ #
61
+ # @param [String] template_template template for template
62
+ def register_template(template_template)
63
+ template_alloc = ::OpenNebula::Template.build_xml
64
+ template = ::OpenNebula::Template.new(template_alloc, client)
65
+
66
+ logger.debug("Registering template with template\n#{template_template}")
67
+ Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { template.allocate(template_template) }
68
+
69
+ template
70
+ end
71
+
72
+ # Prepares a template for a template
73
+ #
74
+ # @param [String] template_dir directory with templates
75
+ # @param [Hash] data used while populating a template
76
+ # @return [String] final template for a template
77
+ def self.prepare_template(template_dir, data)
78
+ template_location = File.join(template_dir, "template.erb")
79
+ fail Nifty::Errors::ArgumentError, "Missing file 'template.erb' in template directory '#{template_dir}'" unless File.exist?(template_location)
80
+
81
+ template = Tilt::ERBTemplate.new(template_location)
82
+ template_content = template.render(Object.new, data)
83
+
84
+ template = Tilt::ERBTemplate.new(File.join(Nifty::GEM_DIR, 'templates', 'template.erb'))
85
+ nifty_template_content = template.render(Object.new, data)
86
+
87
+ whole_template_content = template_content + nifty_template_content
88
+ logger.debug "Populated template template:\n#{whole_template_content}"
89
+ whole_template_content
90
+ end
91
+ end
@@ -0,0 +1,9 @@
1
+ # Namespace for OpenNebula's backend utilities
2
+ module Nifty::Backends::Utils::Opennebula; end
3
+
4
+ require 'nifty/backends/utils/opennebula/helper'
5
+ require 'nifty/backends/utils/opennebula/handler'
6
+ require 'nifty/backends/utils/opennebula/group_handler'
7
+ require 'nifty/backends/utils/opennebula/image_handler'
8
+ require 'nifty/backends/utils/opennebula/template_handler'
9
+ require 'nifty/backends/utils/opennebula/datastore_handler'
@@ -0,0 +1,2 @@
1
+ # Namespace for backends' utilities
2
+ module Nifty::Backends::Utils; end
@@ -0,0 +1,5 @@
1
+ # Namespace for all the backends
2
+ module Nifty::Backends
3
+ require File.join(File.dirname(__FILE__), self.name.demodulize.underscore, 'utils')
4
+ Dir.glob(File.join(File.dirname(__FILE__), self.name.demodulize.underscore, '*.rb')) { |backend_file| require backend_file.chomp('.rb') }
5
+ end
@@ -0,0 +1,202 @@
1
+ require 'thor'
2
+ require 'yell'
3
+
4
+ class Nifty::CommandExecutioner < Thor
5
+ class << self
6
+ # Force Thor to exit with a non-zero return value on failure (after `exit` is called).
7
+ #
8
+ # @return [TrueClass, FalseClass] true if thor fail, false otherwise
9
+ def exit_on_failure?
10
+ true
11
+ end
12
+
13
+ # List all available transfer methods for the backend
14
+ #
15
+ # @param [Nifty::Backend] backend
16
+ # @return [Array] array of transfer method classes that support the backend
17
+ def available_transfer_methods(backend)
18
+ unless Nifty::TransferMethods.constants.include? backend.camelize.to_sym
19
+ fail Nifty::CommandExecutionError, "No backend with name '#{backend}'"
20
+ end
21
+
22
+ clazz = "Nifty::TransferMethods::#{backend.camelize}".constantize
23
+ constants = clazz.constants.map { |sym| sym.to_s.downcase }
24
+ constants.select! do |constant|
25
+ unknown = clazz.const_get(constant.camelize)
26
+
27
+ unknown.respond_to?('transfer_method?') && unknown.transfer_method?
28
+ end
29
+
30
+ constants.sort
31
+ end
32
+
33
+ # List all available backends
34
+ #
35
+ # @return [Array] array of all available backend classes
36
+ def available_backends
37
+ constants = Nifty::Backends.constants.map { |sym| sym.to_s.downcase }
38
+ constants.select! do |constant|
39
+ unknown = Nifty::Backends.const_get(constant.camelize)
40
+
41
+ unknown.respond_to?('backend?') && unknown.backend?
42
+ end
43
+
44
+ constants.sort
45
+ end
46
+ end
47
+
48
+ # global options
49
+ class_option :"appliance-dir",
50
+ :required => true,
51
+ :default => Nifty::Settings['appliance-dir'],
52
+ :type => :string,
53
+ :aliases => '-a',
54
+ :desc => 'Directory from where appliance descriptors will be loaded'
55
+ class_option :"transfer-method",
56
+ :required => true,
57
+ :default => Nifty::Settings['transfer']['method'],
58
+ :type => :string,
59
+ :aliases => '-m',
60
+ :desc => 'Transfer method for image upload'
61
+ class_option :"transfer-destination",
62
+ :default => Nifty::Settings['transfer']['destination'],
63
+ :type => :string,
64
+ :aliases => '-t',
65
+ :desc => 'Image upload destination'
66
+ class_option :"logging-level",
67
+ :required => true,
68
+ :default => Nifty::Settings['logging']['level'],
69
+ :type => :string,
70
+ :enum => Yell::Severities
71
+ class_option :"logging-file",
72
+ :default => Nifty::Settings['logging']['file'],
73
+ :type => :string,
74
+ :desc => 'File to write log to'
75
+ class_option :debug,
76
+ :default => Nifty::Settings['debug'],
77
+ :type => :boolean,
78
+ :desc => 'Runs nifty in debug mode'
79
+
80
+ desc 'version', 'Prints NIFTY\'s version'
81
+ def version
82
+ $stdout.puts Nifty::VERSION
83
+ end
84
+
85
+ desc 'backends', 'Lists all available backends with their description'
86
+ def backends
87
+ backends = self.class.available_backends
88
+ longest = backends.map { |backend| backend.length }.sort.last
89
+ backends.each do |backend|
90
+ $stdout.puts "%-#{longest + 2}s" % "#{backend}" + "# #{Nifty::Backends.const_get(backend.camelize).description}"
91
+ end
92
+ end
93
+
94
+ available_backends.each do |backend|
95
+ backend_clazz = Nifty::Backends.const_get(backend.camelize)
96
+ options = backend_clazz.options
97
+ options.each do |name, parameters|
98
+ parameters[:default] = Nifty::Settings[backend][name.to_s] unless parameters[:default]
99
+ method_option name, parameters
100
+ end
101
+
102
+ class_eval %Q^
103
+ desc '#{backend}', 'Runs NIFTY with backend #{backend}'
104
+ def #{backend}
105
+ start('#{backend}', options)
106
+ end
107
+
108
+ desc '#{backend}-transfer-methods', 'Lists all available transfer methods with their description for #{backend.inspect} backend'
109
+ def #{backend}_transfer_methods
110
+ methods = self.class.available_transfer_methods '#{backend}'
111
+ longest = methods.map { |method| method.length }.sort.last
112
+ methods.each do |method|
113
+ $stdout.puts "%-\#{longest + 2}s" % "\#{method}" + "# \#{Nifty::TransferMethods::#{backend.camelize}.const_get(method.camelize).description}"
114
+ end
115
+ end
116
+ ^
117
+ end
118
+
119
+ private
120
+
121
+ # Starts NIFTY with selected backend
122
+ #
123
+ # @param [String] backend backend's name
124
+ # @param [Hash] options options from command line
125
+ def start(backend, options)
126
+ parameters = options.to_hash.deep_symbolize_keys
127
+ init_log parameters
128
+
129
+ backend = Nifty::Backends.const_get(backend.camelize)
130
+ logger.debug "Selected backend '#{backend.inspect}'"
131
+
132
+ transfer_method = construct_transfer_method(backend, parameters)
133
+ logger.debug "Selected transfer method '#{transfer_method.inspect}'"
134
+
135
+ logger.debug "Parameters: #{parameters}"
136
+
137
+ processor = Nifty::Event::Processor.new(backend, transfer_method, parameters)
138
+ exit processor.process_events
139
+ end
140
+
141
+ # Inits logging according to the settings
142
+ #
143
+ # @param [Hash] parameters
144
+ # @option parameters [String] logging-level
145
+ # @option parameters [String] logging-file file to log to
146
+ # @option parameters [TrueClass, FalseClass] debug debug mode
147
+ # @return [Type] description of returned object
148
+ def init_log(parameters)
149
+ parameters[:"logging-level"] = 'DEBUG' if parameters[:debug]
150
+
151
+ Yell.new :stdout, :name => Object, :level => parameters[:"logging-level"].downcase, :format => Yell::DefaultFormat
152
+ Object.send :include, Yell::Loggable
153
+
154
+ if parameters[:"logging-file"]
155
+ unless (File.exist?(parameters[:"logging-file"]) && File.writable?(parameters[:"logging-file"])) || (File.writable?(File.dirname(parameters[:"logging-file"])))
156
+ logger.error "File #{parameters[:"logging-file"]} isn't writable"
157
+ return
158
+ end
159
+
160
+ logger.adapter :file, parameters[:"logging-file"]
161
+ end
162
+ end
163
+
164
+ # Returns class representing transfer method of specified name
165
+ #
166
+ # @param [Nifty::Backend] backend
167
+ # @param [String] transfer_method_name name of the transfer method
168
+ # @return [Nifty::TransferMethod] transfer method class
169
+ def transfer_method_constant(backend, transfer_method_name)
170
+ transfer_methods = "Nifty::TransferMethods::#{backend.name.demodulize}".constantize
171
+ backend_name = backend.name.demodulize.underscore
172
+ error_msg = "No such transfer method '#{transfer_method_name}' for backend '#{backend_name}'"
173
+ unless transfer_methods.constants.include?(transfer_method_name.camelize.to_sym)
174
+ $stdout.puts error_msg
175
+ exit Nifty::ExitCodes::NO_TRANSFER_METHOD_ERROR_EXIT_CODE
176
+ end
177
+
178
+ transfer_method = transfer_methods.const_get(transfer_method_name.camelize)
179
+ unless transfer_method.respond_to?('backend') && transfer_method.backend == backend
180
+ $stdout.puts error_msg
181
+ exit
182
+ end
183
+
184
+ transfer_method
185
+ end
186
+
187
+ # Returns transfer method according to settings
188
+ #
189
+ # @param [Nifty::Backend] backend
190
+ # @param [Hash] parameters
191
+ # @option parameters [String] transfer-method name of the transfer method
192
+ # @option parameters [String] transfer-destination destination fo the transfer method
193
+ # @return [Nifty::TransferMethod] instance of specified transfer method
194
+ def construct_transfer_method(backend, parameters)
195
+ transfer_method_const = transfer_method_constant(backend, parameters[:"transfer-method"])
196
+
197
+ transfer_method_const.new(parameters[:"transfer-destination"])
198
+ rescue Nifty::Errors::TransferMethodError => ex
199
+ $stdout.puts ex.message
200
+ exit Nifty::ExitCodes::TRANSFER_METHOD_ERROR_EXIT_CODE
201
+ end
202
+ end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::ApiCallTimeoutError < Nifty::Errors::StandardError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::ArgumentError < Nifty::Errors::StandardError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::BackendError < Nifty::Errors::StandardError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Backends::Opennebula::AuthenticationError < Nifty::Errors::Backends::OpennebulaError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Backends::Opennebula::ResourceNotFoundError < Nifty::Errors::Backends::OpennebulaError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Backends::Opennebula::ResourceRetrievalError < Nifty::Errors::Backends::OpennebulaError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Backends::Opennebula::ResourceStateError < Nifty::Errors::Backends::OpennebulaError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Backends::Opennebula::StubError < Nifty::Errors::Backends::OpennebulaError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Backends::Opennebula::UserNotAuthorizedError < Nifty::Errors::Backends::OpennebulaError; end
@@ -0,0 +1,5 @@
1
+ module Nifty::Errors::Backends::Opennebula
2
+ require File.join(File.dirname(__FILE__), 'opennebula_error')
3
+ require File.join(File.dirname(__FILE__), self.name.demodulize.underscore, 'authentication_error')
4
+ Dir.glob(File.join(File.dirname(__FILE__), self.name.demodulize.underscore, '*.rb')) { |error_file| require error_file.chomp('.rb') }
5
+ end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Backends::OpennebulaError < Nifty::Errors::BackendError; end
@@ -0,0 +1,4 @@
1
+ module Nifty::Errors::Backends
2
+ require File.join(File.dirname(__FILE__), 'backend_error')
3
+ Dir.glob(File.join(File.dirname(__FILE__), self.name.demodulize.underscore, '*.rb')) { |error_file| require error_file.chomp('.rb') }
4
+ end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::CommandExecutionError < Nifty::Errors::StandardError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Event::ConverterError < Nifty::Errors::StandardError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Event::LoaderError < Nifty::Errors::StandardError; end
@@ -0,0 +1,5 @@
1
+ module Nifty::Errors::Event
2
+ require File.join(File.dirname(__FILE__), 'event', 'loader_error')
3
+ require File.join(File.dirname(__FILE__), 'event', 'converter_error')
4
+ Dir.glob(File.join(File.dirname(__FILE__), self.name.demodulize.underscore, '*.rb')) { |error_file| require error_file.chomp('.rb') }
5
+ end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Events::EventError < Nifty::Errors::StandardError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Events::ExpirationEventError < Nifty::Errors::Events::EventError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::Events::RegistrationEventError < Nifty::Errors::Events::EventError; end
@@ -0,0 +1,4 @@
1
+ module Nifty::Errors::Events
2
+ require File.join(File.dirname(__FILE__), 'events', 'event_error')
3
+ Dir.glob(File.join(File.dirname(__FILE__), self.name.demodulize.underscore, '*.rb')) { |error_file| require error_file.chomp('.rb') }
4
+ end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::StandardError < ::StandardError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::TransferMethodError < Nifty::Errors::ArgumentError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::TransferMethods::DestinationNotDirectoryError < Nifty::Errors::TransferMethodError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::TransferMethods::DestinationNotWritableError < Nifty::Errors::TransferMethodError; end
@@ -0,0 +1 @@
1
+ class Nifty::Errors::TransferMethods::ImageFileNotReadableError < Nifty::Errors::TransferMethodError; end
@@ -0,0 +1,4 @@
1
+ module Nifty::Errors::TransferMethods
2
+ require File.join(File.dirname(__FILE__), 'transfer_method_error')
3
+ Dir.glob(File.join(File.dirname(__FILE__), self.name.demodulize.underscore, '*.rb')) { |error_file| require error_file.chomp('.rb') }
4
+ end
@@ -0,0 +1,10 @@
1
+ # Namespace for all the exceptions
2
+ module Nifty::Errors
3
+ require File.join(File.dirname(__FILE__), 'errors', 'standard_error')
4
+ require File.join(File.dirname(__FILE__), 'errors', 'argument_error')
5
+ require File.join(File.dirname(__FILE__), 'errors', 'event')
6
+ require File.join(File.dirname(__FILE__), 'errors', 'backends')
7
+ require File.join(File.dirname(__FILE__), 'errors', 'transfer_methods')
8
+ require File.join(File.dirname(__FILE__), 'errors', 'events')
9
+ Dir.glob(File.join(File.dirname(__FILE__), self.name.demodulize.underscore, '*.rb')) { |error_file| require error_file.chomp('.rb') }
10
+ end
@@ -0,0 +1,29 @@
1
+ # Converts appliances into events
2
+ #
3
+ # @author Michal Kimle
4
+ class Nifty::Event::Converter
5
+ # Converts appliance into event
6
+ #
7
+ # @param [Cloud::Appliance::Descriptor::Appliance] appliance
8
+ # @param [Nifty::Backend] backend
9
+ # @param [Nifty::TransferMethod] transfer_method
10
+ # @param [Hash] parameters
11
+ # @raise [Nifty::Errors::Event::ConverterError] when something goes wrong while conversion
12
+ # @return [Nifty::Event] description of returned object
13
+ def self.convert_appliance(appliance, backend, transfer_method, parameters)
14
+ events_module = "Nifty::Events::#{backend.name.demodulize}".constantize
15
+
16
+ logger.debug "Converting appliance #{appliance.inspect}"
17
+ event_type = "#{appliance.action}_event".camelize
18
+
19
+ fail Nifty::Errors::Event::ConverterError, "No such event type for action #{appliance.action.inspect}" unless events_module.constants.include?(event_type.to_sym)
20
+ event_class = events_module.const_get(event_type)
21
+
22
+ fail Nifty::Errors::Event::ConverterError, "Class #{event_class.inspect} doesn't represent an event" unless (event_class.respond_to?('event?') && event_class.event? && event_class.public_instance_methods.include?(:run))
23
+
24
+ event = backend.create_event(event_class, appliance, transfer_method, parameters)
25
+ logger.debug "Converted event: #{event.inspect}"
26
+
27
+ event
28
+ end
29
+ end