nifty 0.0.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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