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,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'