nifty 0.0.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|