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.
- checksums.yaml +4 -4
- data/README.md +79 -12
- data/bin/nifty +2 -0
- data/config/nifty.yml +18 -0
- data/config/templates/image.erb +38 -0
- data/config/templates/template.erb +26 -0
- data/lib/nifty/backend.rb +55 -0
- data/lib/nifty/backends/opennebula.rb +109 -0
- data/lib/nifty/backends/utils/opennebula/datastore_handler.rb +36 -0
- data/lib/nifty/backends/utils/opennebula/group_handler.rb +23 -0
- data/lib/nifty/backends/utils/opennebula/handler.rb +60 -0
- data/lib/nifty/backends/utils/opennebula/helper.rb +44 -0
- data/lib/nifty/backends/utils/opennebula/image_handler.rb +209 -0
- data/lib/nifty/backends/utils/opennebula/template_handler.rb +91 -0
- data/lib/nifty/backends/utils/opennebula.rb +9 -0
- data/lib/nifty/backends/utils.rb +2 -0
- data/lib/nifty/backends.rb +5 -0
- data/lib/nifty/command_executioner.rb +202 -0
- data/lib/nifty/errors/api_call_timeout_error.rb +1 -0
- data/lib/nifty/errors/argument_error.rb +1 -0
- data/lib/nifty/errors/backend_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/authentication_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/resource_not_found_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/resource_retrieval_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/resource_state_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/stub_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/user_not_authorized_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula.rb +5 -0
- data/lib/nifty/errors/backends/opennebula_error.rb +1 -0
- data/lib/nifty/errors/backends.rb +4 -0
- data/lib/nifty/errors/command_execution_error.rb +1 -0
- data/lib/nifty/errors/event/converter_error.rb +1 -0
- data/lib/nifty/errors/event/loader_error.rb +1 -0
- data/lib/nifty/errors/event.rb +5 -0
- data/lib/nifty/errors/events/event_error.rb +1 -0
- data/lib/nifty/errors/events/expiration_event_error.rb +1 -0
- data/lib/nifty/errors/events/registration_event_error.rb +1 -0
- data/lib/nifty/errors/events.rb +4 -0
- data/lib/nifty/errors/standard_error.rb +1 -0
- data/lib/nifty/errors/transfer_method_error.rb +1 -0
- data/lib/nifty/errors/transfer_methods/destination_not_directory_error.rb +1 -0
- data/lib/nifty/errors/transfer_methods/destination_not_writable_error.rb +1 -0
- data/lib/nifty/errors/transfer_methods/image_file_not_readable_error.rb +1 -0
- data/lib/nifty/errors/transfer_methods.rb +4 -0
- data/lib/nifty/errors.rb +10 -0
- data/lib/nifty/event/converter.rb +29 -0
- data/lib/nifty/event/loader.rb +27 -0
- data/lib/nifty/event/processor.rb +96 -0
- data/lib/nifty/event.rb +6 -0
- data/lib/nifty/events/event.rb +32 -0
- data/lib/nifty/events/opennebula/event.rb +23 -0
- data/lib/nifty/events/opennebula/expiration_event.rb +32 -0
- data/lib/nifty/events/opennebula/metadata_update_event.rb +12 -0
- data/lib/nifty/events/opennebula/registration_event.rb +113 -0
- data/lib/nifty/events/opennebula/utils/events_common.rb +69 -0
- data/lib/nifty/events/opennebula/utils.rb +4 -0
- data/lib/nifty/events/opennebula.rb +6 -0
- data/lib/nifty/events.rb +5 -0
- data/lib/nifty/exit_codes.rb +8 -0
- data/lib/nifty/settings.rb +18 -0
- data/lib/nifty/transfer_method.rb +69 -0
- data/lib/nifty/transfer_methods/opennebula/cp.rb +52 -0
- data/lib/nifty/transfer_methods/opennebula/noop.rb +27 -0
- data/lib/nifty/transfer_methods/opennebula.rb +4 -0
- data/lib/nifty/transfer_methods.rb +4 -0
- data/lib/nifty/version.rb +1 -1
- data/lib/nifty.rb +20 -2
- data/nifty.gemspec +7 -0
- data/schema/appliance.json +295 -0
- data/templates/image.erb +8 -0
- data/templates/template.erb +13 -0
- 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
|
data/lib/nifty/event.rb
ADDED
@@ -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,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,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
|
data/lib/nifty/events.rb
ADDED
@@ -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
|
data/lib/nifty/version.rb
CHANGED
data/lib/nifty.rb
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
-
|
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
|
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'
|