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,27 @@
1
+ require 'cloud-appliance-descriptor'
2
+ require 'json-schema'
3
+
4
+ # Takes care of loading appliance descriptors
5
+ #
6
+ # @author Michal Kimle
7
+ class Nifty::Event::Loader
8
+ # Loads appliance from the file
9
+ #
10
+ # @param [String] filename
11
+ # @raise [Nifty::Errors::Event::LoaderError] when appliance descriptor is invalid
12
+ # @return [Cloud::Appliance::Descriptor::Appliance] loaded appliance
13
+ def self.load_appliance(filename)
14
+ logger.debug "Loading appliance from file #{filename.inspect}..."
15
+ fail Nifty::Errors::Event::LoaderError, "Descriptor file #{filename.inspect} is not readable" unless File.readable?(filename)
16
+
17
+ JSON::Validator.validate!(Nifty::APPLIANCE_SCHEMA, filename)
18
+
19
+ file = File.read(filename)
20
+ appliance = Cloud::Appliance::Descriptor::Appliance.from_json(file)
21
+ logger.debug "Loaded appliance: #{appliance.inspect}"
22
+
23
+ appliance
24
+ rescue JSON::Schema::ValidationError => ex
25
+ fail Nifty::Errors::Event::LoaderError, ex
26
+ end
27
+ end
@@ -0,0 +1,96 @@
1
+ require 'fileutils'
2
+
3
+ # Processing of events
4
+ #
5
+ # @author Michal Kimle
6
+ # @attr_reader [Nifty::Backend] backend
7
+ # @attr_reader [Nifty::TransferMethod] transfer_method
8
+ # @attr_reader [Hash] parameters
9
+ class Nifty::Event::Processor
10
+ attr_reader :backend, :transfer_method, :parameters, :error_code
11
+
12
+ # Constructor
13
+ #
14
+ # @param [Nifty::Backend] backend
15
+ # @param [Nifty::TransferMethod] transfer_method
16
+ # @param [Hash] parameters
17
+ def initialize(backend, transfer_method, parameters)
18
+ @backend = backend
19
+ @transfer_method = transfer_method
20
+ @parameters = parameters
21
+ @error_code = Nifty::ExitCodes::NO_ERROR_EXIT_CODE
22
+ end
23
+
24
+ # Runs the whole event processing
25
+ #
26
+ def process_events
27
+ run_backend_pre
28
+ run_events
29
+ run_backend_post
30
+
31
+ error_code
32
+ end
33
+
34
+ # Runs backend's preprocessing routine
35
+ #
36
+ def run_backend_pre
37
+ logger.debug('Running backend pre-processing...')
38
+ backend.pre(parameters) if backend.respond_to? 'pre'
39
+ end
40
+
41
+ # Runs backend's postprocessing routine
42
+ #
43
+ def run_backend_post
44
+ logger.debug('Running backend post-processing...')
45
+ backend.post(parameters) if backend.respond_to? 'post'
46
+ end
47
+
48
+ # Takes care of event processing. All the events are loaded, converted and run.
49
+ #
50
+ def run_events
51
+ events = prepare_events
52
+ logger.debug("Events ready to run: #{events}")
53
+ events.each do |event, file|
54
+ begin
55
+ event.run
56
+
57
+ # clean event's descriptor so it won't be processed again
58
+ FileUtils.rm file
59
+ rescue Nifty::Errors::Events::EventError => ex
60
+ logger.error "Unable to process event #{event.inspect} from descriptor #{file.inspect}: #{ex.message}."
61
+ @error_code = Nifty::ExitCodes::EVENT_PROCESSING_ERROR_EXIT_CODE
62
+ break
63
+ rescue SystemCallError => ex
64
+ logger.warn "Cannot delete descriptor file #{file.inspect} of already processed event: #{ex.message}. Please, do so manually."
65
+ @error_code = Nifty::ExitCodes::EVENT_CLEANUP_ERROR_EXIT_CODE
66
+ break
67
+ end
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ # Prepares events for processing
74
+ #
75
+ def prepare_events
76
+ appliance_dir = parameters[:"appliance-dir"]
77
+ logger.warn "Descriptor directory #{appliance_dir.inspect} doesn't seem to be readable" unless File.readable? appliance_dir
78
+
79
+ events = {}
80
+ # each event has its own descriptor
81
+ Dir.glob(File.join(appliance_dir, '*.json')).sort.each do |file|
82
+ begin
83
+ appliance = Nifty::Event::Loader.load_appliance(file)
84
+ event = Nifty::Event::Converter.convert_appliance(appliance, backend, transfer_method, parameters)
85
+
86
+ events[event] = file
87
+ rescue Nifty::Errors::Event::LoaderError, Nifty::Errors::BackendError => ex
88
+ logger.error "Error occured while event #{file.inspect} preparation: #{ex.message}."
89
+ @error_code = Nifty::ExitCodes::EVENT_PREPARATION_ERROR_EXIT_CODE
90
+ break
91
+ end
92
+ end
93
+
94
+ events
95
+ end
96
+ end
@@ -0,0 +1,6 @@
1
+ # Namespace for event processing
2
+ module Nifty::Event; end
3
+
4
+ require 'nifty/event/loader'
5
+ require 'nifty/event/converter'
6
+ require 'nifty/event/processor'
@@ -0,0 +1,32 @@
1
+ # Abstract class for all events
2
+ #
3
+ # @author Michal Kimle
4
+ # @abstract
5
+ # @attr_reader [Cloud::Appliance::Descriptor::Appliance] appliance appliance representing an event
6
+ # @attr_reader [Nifty::TransferMethod] transfer_method event's transfer method
7
+ class Nifty::Events::Event
8
+ attr_reader :appliance, :transfer_method
9
+
10
+ # Constructor
11
+ # @abstract
12
+ # @param [Cloud::Appliance::Descriptor::Appliance] appliance appliance representing an event
13
+ # @param [Nifty::TransferMethod] transfer_method event's transfer method
14
+ def initialize(appliance, transfer_method)
15
+ appliance.os = Cloud::Appliance::Descriptor::Os.new unless appliance.os
16
+ @appliance = appliance
17
+ @transfer_method = transfer_method
18
+ end
19
+
20
+ # Helper method to recognize NIFTY event
21
+ #
22
+ # @return [TrueClass,FalseClass] whether class is an event or not
23
+ def self.event?
24
+ false
25
+ end
26
+
27
+ # Runs the event
28
+ #
29
+ # @raise Nifty::Errors::Events::EventError
30
+ def run
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ # OpenNebula event
2
+ #
3
+ # @author Michal Kimle
4
+ # @attr_reader [OpenNebula::Client] client
5
+ # @attr_reader [Array] datastores
6
+ # @attr_reader [Hash] parameters
7
+ class Nifty::Events::Opennebula::Event < Nifty::Events::Event
8
+ attr_reader :client, :datastores, :parameters
9
+
10
+ # Constructor
11
+ #
12
+ # @param [Cloud::Appliance::Descriptor::Appliance] appliance
13
+ # @param [Nifty::TransferMethod] transfer_method
14
+ # @param [OpenNebula::Client] client
15
+ # @param [Array] datastores
16
+ # @param [Hash] parameters
17
+ def initialize(appliance, transfer_method, client, datastores, parameters)
18
+ super(appliance, transfer_method)
19
+ @client = client
20
+ @datastores = datastores
21
+ @parameters = parameters
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ # OpenNebula expiration event
2
+ #
3
+ # @author Michal Kimle
4
+ class Nifty::Events::Opennebula::ExpirationEvent < Nifty::Events::Opennebula::Event
5
+ include Nifty::Events::Opennebula::Utils::EventsCommon
6
+
7
+ # @see Nifty::Events::Event#event?
8
+ def self.event?
9
+ true
10
+ end
11
+
12
+ attr_accessor :image_handler, :template_handler
13
+
14
+ # @see Nifty::Events::Opennebula::Event#initialize
15
+ # @attr [Nifty::Backends::Utils::Opennebula::ImageHandler] image_handler
16
+ # @attr [Nifty::Backends::Utils::Opennebula::TemplateHandler] template_handler
17
+ def initialize(appliance, transfer_method, client, datastores, parameters)
18
+ super(appliance, transfer_method, client, datastores, parameters)
19
+
20
+ @image_handler = Nifty::Backends::Utils::Opennebula::ImageHandler.new(client)
21
+ @template_handler = Nifty::Backends::Utils::Opennebula::TemplateHandler.new(client)
22
+ end
23
+
24
+ # @see Nifty::Events::Event#run
25
+ def run
26
+ logger.debug("Runnig event #{self.inspect}")
27
+
28
+ expire_appliance(template_handler, image_handler, appliance, parameters)
29
+ rescue Nifty::Errors::Backends::OpennebulaError, Nifty::Errors::ApiCallTimeoutError => ex
30
+ fail Nifty::Errors::Events::EventError, ex
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ # OpenNebula metadata update event
2
+ # Not implemented yet!
3
+ #
4
+ # @author Michal Kimle
5
+ class Nifty::Events::Opennebula::MetadataUpdateEvent < Nifty::Events::Opennebula::Event
6
+ def self.event?
7
+ true
8
+ end
9
+
10
+ def run
11
+ end
12
+ end
@@ -0,0 +1,113 @@
1
+ require 'securerandom'
2
+
3
+ # OpenNebula registration event
4
+ #
5
+ # @author Michal Kimle
6
+ class Nifty::Events::Opennebula::RegistrationEvent < Nifty::Events::Opennebula::Event
7
+ include Nifty::Events::Opennebula::Utils::EventsCommon
8
+
9
+ # @see Nifty::Events::Event#event?
10
+ def self.event?
11
+ true
12
+ end
13
+
14
+ attr_accessor :image_handler, :template_handler, :group_handler, :original_disks
15
+
16
+ # @see Nifty::Events::Opennebula::Event#initialize
17
+ # @attr [Nifty::Backends::Utils::Opennebula::ImageHandler] image_handler
18
+ # @attr [Nifty::Backends::Utils::Opennebula::TemplateHandler] template_handler
19
+ # @attr [Nifty::Backends::Utils::Opennebula::GroupHandler] group_handler
20
+ # @attr [Array] original_disks array of original image file paths before transfer
21
+ def initialize(appliance, transfer_method, client, datastores, parameters)
22
+ super(appliance, transfer_method, client, datastores, parameters)
23
+
24
+ @image_handler = Nifty::Backends::Utils::Opennebula::ImageHandler.new(client)
25
+ @template_handler = Nifty::Backends::Utils::Opennebula::TemplateHandler.new(client)
26
+ @group_handler = Nifty::Backends::Utils::Opennebula::GroupHandler.new(client)
27
+ @original_disks = []
28
+ end
29
+
30
+ # @see Nifty::Events::Event#run
31
+ def run
32
+ logger.debug("Runnig event #{self.inspect}")
33
+ transfer_disks
34
+
35
+ expire_appliance(template_handler, image_handler, appliance, parameters)
36
+
37
+ groups = groups(group_handler, appliance)
38
+ # due to OpenNebula restrictions appliances have to be registered separately for each datastore and each group
39
+ datastores.each do |datastore|
40
+ groups.each do |group|
41
+ image_data = register_disks(group, datastore)
42
+ register_appliance(image_data, group, datastore)
43
+ end
44
+ end
45
+
46
+ clean_original_disks
47
+ rescue Nifty::Errors::Backends::OpennebulaError, Nifty::Errors::TransferMethodError, Nifty::Errors::ApiCallTimeoutError => ex
48
+ fail Nifty::Errors::Events::EventError, ex
49
+ ensure
50
+ clean_copied_disks
51
+ end
52
+
53
+ private
54
+
55
+ # Calls a selected transfer method on all disks within an appliance
56
+ def transfer_disks
57
+ appliance.disks.each do |disk|
58
+ original_disks << disk.path
59
+ disk.path = transfer_method.transfer disk.path
60
+ end
61
+ end
62
+
63
+ # Calls a selected transfer method's cleanup for original disks
64
+ def clean_original_disks
65
+ original_disks.each do |disk|
66
+ transfer_method.clean_original disk
67
+ end
68
+ end
69
+
70
+ # Calls a selected transfer method's cleanup for previously transfered disks
71
+ def clean_copied_disks
72
+ original_disks.each do |disk|
73
+ transfer_method.clean_copy disk
74
+ end
75
+ end
76
+
77
+ # Registers disks of event's applaince
78
+ #
79
+ # @param [String] group
80
+ # @param [OpenNebula::Datastore] datastore
81
+ # @return [Hash] hash containing username of the user owning the disks in OpenNebula and their names
82
+ def register_disks(group, datastore)
83
+ disk_names = []
84
+ image = nil
85
+
86
+ appliance.disks.each_with_index do |disk, index|
87
+ logger.debug("Registering disk #{disk.inspect}")
88
+ name = parameters[:"description-naming"] ? "#{appliance.identifier}-#{appliance.version}-#{'%02d' % (index + 1)}@#{datastore.name}" : ::SecureRandom.uuid
89
+ template = Nifty::Backends::Utils::Opennebula::ImageHandler.prepare_template(parameters[:"template-dir"], appliance: appliance, disk: disk, name: name)
90
+ image = image_handler.register_image(template, datastore)
91
+ Nifty::Backends::Utils::Opennebula::Handler.chown(image, Nifty::Backends::Utils::Opennebula::Handler::LEAVE_AS_IS, group.id)
92
+ Nifty::Backends::Utils::Opennebula::Handler.chmod(image, parameters[:permissions])
93
+ disk_names << name
94
+ end
95
+
96
+ { :username => image['UNAME'], :disk_names => disk_names }
97
+ end
98
+
99
+ # Registers an appliance in OpenNebula
100
+ # Creates VM templates pointing to previously registered disks in OpenNebula
101
+ #
102
+ # @param [Hash] image_data hash containing username of the user owning the disks in OpenNebula and their names
103
+ # @param [String] group
104
+ # @param [String] datastore
105
+ def register_appliance(image_data, group, datastore)
106
+ logger.debug("Registering appliance #{appliance.inspect}")
107
+ name = parameters[:"description-naming"] ? "#{appliance.identifier}@#{datastore.name}" : ::SecureRandom.uuid
108
+ template_template = Nifty::Backends::Utils::Opennebula::TemplateHandler.prepare_template(parameters[:"template-dir"], appliance: appliance, disk_names: image_data[:disk_names], name: name, username: image_data[:username])
109
+ template = template_handler.register_template(template_template)
110
+ Nifty::Backends::Utils::Opennebula::Handler.chown(template, Nifty::Backends::Utils::Opennebula::Handler::LEAVE_AS_IS, group.id)
111
+ Nifty::Backends::Utils::Opennebula::Handler.chmod(template, parameters[:permissions])
112
+ end
113
+ end
@@ -0,0 +1,69 @@
1
+ # Namespace for method common among multiple OpenNebula event types
2
+ module Nifty::Events::Opennebula::Utils::EventsCommon
3
+ # Expires whole appliance (both images and template)
4
+ #
5
+ # @param [Nifty::Backends::Utils::Opennebula::TemplateHandler] template_handler
6
+ # @param [Nifty::Backends::Utils::Opennebula::ImageHandler] image_handler
7
+ # @param [Cloud::Appliance::Descriptor::Appliance] appliance
8
+ # @param [Hash] parameters
9
+ def expire_appliance(template_handler, image_handler, appliance, parameters)
10
+ delete_appliance(template_handler, appliance.identifier)
11
+ outdate_disks(image_handler, appliance.identifier)
12
+ expire_disks(image_handler, appliance, parameters[:"disk-expiration"])
13
+ end
14
+
15
+ # Returns OpenNebula groups specified in appliance
16
+ #
17
+ # @param [Nifty::Backends::Utils::Opennebula::GroupHandler] group_handler
18
+ # @param [Cloud::Appliance::Descriptor::Appliance] appliance
19
+ # @return [Array] Array of groups
20
+ def groups(group_handler, appliance)
21
+ groups = []
22
+ appliance.groups.each do |group_name|
23
+ group = group_handler.group(group_name)
24
+ fail Nifty::Errors::Backends::Opennebula::ResourceNotFoundError, "No such group with name #{group_name.inspect}" unless group
25
+
26
+ groups << group
27
+ end
28
+
29
+ groups
30
+ end
31
+
32
+ private
33
+
34
+ # Outdates disks with specified appliance ID
35
+ #
36
+ # @param [Nifty::Backends::Utils::Opennebula::ImageHandler] image_handler
37
+ # @param [String] appliance_id
38
+ def outdate_disks(image_handler, appliance_id)
39
+ registered_disks = image_handler.images(appliance_id)
40
+ logger.debug('Outdating registered disks...')
41
+ registered_disks.each { |disk| image_handler.outdate_image(disk) }
42
+ end
43
+
44
+ # Expires disks with specified appliance ID
45
+ # Depending on the settings expires all disks or only disks with old version
46
+ #
47
+ # @param [Nifty::Backends::Utils::Opennebula::ImageHandler] image_handler
48
+ # @param [Cloud::Appliance::Descriptor::Appliance] appliance
49
+ # @param [TrueClass,FalseClass] disk_expiration whether expire all disks or just outdated ones
50
+ def expire_disks(image_handler, appliance, disk_expiration)
51
+ registered_disks = disk_expiration ? image_handler.images(appliance.identifier) : image_handler.images_by_version(appliance.version)
52
+ logger.debug('Expiring registered disks...')
53
+ registered_disks.each do |disk|
54
+ image_handler.expire_image(disk)
55
+ Nifty::Backends::Utils::Opennebula::Handler.chown(disk, Nifty::Backends::Utils::Opennebula::Handler::ONEADMIN_ID, Nifty::Backends::Utils::Opennebula::Handler::ONEADMIN_ID)
56
+ Nifty::Backends::Utils::Opennebula::Handler.chmod(disk, Nifty::Backends::Utils::Opennebula::Handler::OWNER_OCTET)
57
+ end
58
+ end
59
+
60
+ # Deletes template with specified appliance ID
61
+ #
62
+ # @param [Nifty::Backends::Utils::Opennebula::TemplateHandler] template_handler
63
+ # @param [String] appliance_id
64
+ def delete_appliance(template_handler, appliance_id)
65
+ registered_appliances = template_handler.templates(appliance_id)
66
+ logger.debug('Deleting registered templates...')
67
+ registered_appliances.each { |template| template_handler.delete_template template }
68
+ end
69
+ end
@@ -0,0 +1,4 @@
1
+ # Namespace for OpenNebula events' utilities
2
+ module Nifty::Events::Opennebula::Utils
3
+ require File.join(File.dirname(__FILE__), "#{self.name.demodulize.underscore}", 'events_common')
4
+ end
@@ -0,0 +1,6 @@
1
+ # Namespace for OpenNebula events
2
+ module Nifty::Events::Opennebula
3
+ require File.join(File.dirname(__FILE__), "#{self.name.demodulize.underscore}", 'utils')
4
+ require File.join(File.dirname(__FILE__), "#{self.name.demodulize.underscore}", 'event')
5
+ Dir.glob(File.join(File.dirname(__FILE__), "#{self.name.demodulize.underscore}", '*.rb')) { |event_file| require event_file.chomp('.rb') }
6
+ end
@@ -0,0 +1,5 @@
1
+ # Namespace for all the events
2
+ module Nifty::Events; end
3
+
4
+ require 'nifty/events/event'
5
+ require 'nifty/events/opennebula'
@@ -0,0 +1,8 @@
1
+ class Nifty::ExitCodes
2
+ NO_ERROR_EXIT_CODE = 0
3
+ EVENT_PROCESSING_ERROR_EXIT_CODE = 1
4
+ EVENT_CLEANUP_ERROR_EXIT_CODE = 2
5
+ EVENT_PREPARATION_ERROR_EXIT_CODE = 3
6
+ NO_TRANSFER_METHOD_ERROR_EXIT_CODE = 4
7
+ TRANSFER_METHOD_ERROR_EXIT_CODE = 5
8
+ end
@@ -0,0 +1,18 @@
1
+ require 'settingslogic'
2
+
3
+ # Class for configuration management
4
+ #
5
+ # @author Michal Kimle
6
+ class Nifty::Settings < Settingslogic
7
+ CONFIGURATION = 'nifty.yml'
8
+
9
+ # three possible configuration file locations in order by preference
10
+ # if configuration file is found rest of the locations are ignored
11
+ source "#{ENV['HOME']}/.nifty/#{CONFIGURATION}"\
12
+ if File.exist?("#{ENV['HOME']}/.nifty/#{CONFIGURATION}")
13
+ source "/etc/nifty/#{CONFIGURATION}"\
14
+ if File.exist?("/etc/nifty/#{CONFIGURATION}")
15
+ source "#{File.dirname(__FILE__)}/../../config/#{CONFIGURATION}"
16
+
17
+ namespace 'production'
18
+ end
@@ -0,0 +1,69 @@
1
+ require 'fileutils'
2
+
3
+ # Abstract base class for all trasfer methods
4
+ #
5
+ # @author Michal Kimle
6
+ # @abstract
7
+ # @attr_reader [String] destination path to destination directory for the transfer method
8
+ class Nifty::TransferMethod
9
+ attr_reader :destination
10
+
11
+ class << self
12
+ # Helper method to recognize NIFTY transfer method
13
+ #
14
+ # @return [TrueClass, FalseClass] whether or not class is a NIFTY transfer method
15
+ def transfer_method?
16
+ false
17
+ end
18
+
19
+ # Returns textual description of the transfer method
20
+ # Used in help messages.
21
+ #
22
+ # @abstract
23
+ # @return [String, nil] textual description of the transfer method
24
+ def description
25
+ nil
26
+ end
27
+
28
+ # Returns backend class supported by the transfer method
29
+ #
30
+ # @abstract
31
+ # @return [Nifty::Backend] backend class supported by the transfer method
32
+ def backend
33
+ nil
34
+ end
35
+ end
36
+
37
+ # Constructor
38
+ #
39
+ # @param [String] destination for the transfer method
40
+ def initialize(destination)
41
+ @destination = destination
42
+ end
43
+
44
+ # Transfers file to the destination
45
+ #
46
+ # @param [String] file to be transfered
47
+ # @return [String] path to the transfered file
48
+ def transfer(file)
49
+ fail Nifty::Errors::TransferMethods::ImageFileNotReadableError, "Image file #{file} is not readable" unless File.readable?(file)
50
+ end
51
+
52
+ # Removes original file before transfer method
53
+ #
54
+ # @param [String] file to be cleaned
55
+ def clean_original(file)
56
+ logger.debug("Deleting files #{file.inspect}")
57
+ FileUtils.rm file
58
+ rescue SystemCallError => ex
59
+ logger.warn("Cannot delete file #{file.inspect}, #{ex.message}")
60
+ end
61
+
62
+ # Removes file copy if any created by transfer method
63
+ #
64
+ # @abstract
65
+ # @param [String] file to be cleaned
66
+ def clean_copy(file)
67
+ nil
68
+ end
69
+ end
@@ -0,0 +1,52 @@
1
+ # Copy transfer method
2
+ # Copies file to the destination and clens it after the event is processed
3
+ class Nifty::TransferMethods::Opennebula::Cp < Nifty::TransferMethod
4
+ class << self
5
+ # @see Nifty::TransferMethod#transfer_method?
6
+ def transfer_method?
7
+ true
8
+ end
9
+
10
+ # @see Nifty::TransferMethod#description
11
+ def description
12
+ 'Copy transfer method - copies images localy within one host'
13
+ end
14
+
15
+ # @see Nifty::TransferMethod#backend
16
+ def backend
17
+ Nifty::Backends::Opennebula
18
+ end
19
+ end
20
+
21
+ # @see Nifty::TransferMethod#initialize
22
+ def initialize(destination)
23
+ fail Nifty::Errors::TransferMethods::DestinationNotDirectoryError, "Destination #{destination.inspect} is not a directory" unless (destination && File.directory?(destination))
24
+ fail Nifty::Errors::TransferMethods::DestinationNotWritableError, "Destination directory #{destination.inspect} is not writable" unless File.writable?(destination)
25
+
26
+ super(destination)
27
+ end
28
+
29
+ # @see Nifty::TransferMethod#transfer
30
+ def transfer(file)
31
+ super(file)
32
+
33
+ logger.debug("Copying file #{file.inspect} to destination #{destination.inspect}")
34
+ FileUtils.cp file, destination
35
+ destination_file file
36
+ end
37
+
38
+ # @see Nifty::TransferMethod#clean_copy
39
+ def clean_copy(file)
40
+ df = destination_file file
41
+ logger.debug("Deleting files #{df.inspect}")
42
+ FileUtils.rm df
43
+ rescue SystemCallError => ex
44
+ logger.warn("Cannot delete file #{df.inspect}, #{ex.message}")
45
+ end
46
+
47
+ private
48
+
49
+ def destination_file(file)
50
+ File.join(destination, File.basename(file))
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ # No operation transfer method
2
+ # Leaves file as it is
3
+ class Nifty::TransferMethods::Opennebula::Noop < Nifty::TransferMethod
4
+ class << self
5
+ # @see Nifty::TransferMethod#transfer_method?
6
+ def transfer_method?
7
+ true
8
+ end
9
+
10
+ # @see Nifty::TransferMethod#description?
11
+ def description
12
+ "No operation transfer method - doesn't change location of images"
13
+ end
14
+
15
+ # @see Nifty::TransferMethod#backend
16
+ def backend
17
+ Nifty::Backends::Opennebula
18
+ end
19
+ end
20
+
21
+ # @see Nifty::TransferMethod#transfer
22
+ def transfer(file)
23
+ super(file)
24
+
25
+ file
26
+ end
27
+ end
@@ -0,0 +1,4 @@
1
+ # Namespace for openNebula transfer methods
2
+ module Nifty::TransferMethods::Opennebula
3
+ Dir.glob(File.join(File.dirname(__FILE__), "#{self.name.demodulize.underscore}", '*.rb')) { |transfer_method_file| require transfer_method_file.chomp('.rb') }
4
+ end
@@ -0,0 +1,4 @@
1
+ # Namespace for transfer methods
2
+ module Nifty::TransferMethods
3
+ require 'nifty/transfer_methods/opennebula'
4
+ end
data/lib/nifty/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Nifty
2
- VERSION = "0.0.1"
2
+ VERSION = "0.2.2"
3
3
  end
data/lib/nifty.rb CHANGED
@@ -1,3 +1,21 @@
1
- module Nifty; end
1
+ # Namespace for the whole NIFTY project
2
+ module Nifty
3
+ GEM_DIR = File.realdirpath(File.join(File.dirname(__FILE__), '..'))
4
+ APPLIANCE_SCHEMA = File.join(GEM_DIR, 'schema', 'appliance.json')
5
+ API_CALL_TIMEOUT = 60
6
+ API_POLLING_WAIT = 5
7
+ end
2
8
 
3
- require "nifty/version"
9
+ require 'active_support/all'
10
+
11
+ require 'nifty/exit_codes'
12
+ require 'nifty/errors'
13
+ require 'nifty/settings'
14
+ require 'nifty/version'
15
+ require 'nifty/transfer_method'
16
+ require 'nifty/transfer_methods'
17
+ require 'nifty/backend'
18
+ require 'nifty/backends'
19
+ require 'nifty/command_executioner'
20
+ require 'nifty/event'
21
+ require 'nifty/events'