cloudkeeper-one 1.0.0

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 (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +48 -0
  6. data/.travis.yml +22 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.txt +17 -0
  10. data/README.md +98 -0
  11. data/Rakefile +17 -0
  12. data/bin/cloudkeeper-one +5 -0
  13. data/cloudkeeper-one.gemspec +44 -0
  14. data/config/cloudkeeper-one.yml +23 -0
  15. data/config/templates/image.erb +20 -0
  16. data/config/templates/template.erb +19 -0
  17. data/lib/cloudkeeper/one/appliance_actions/list.rb +68 -0
  18. data/lib/cloudkeeper/one/appliance_actions/registration.rb +73 -0
  19. data/lib/cloudkeeper/one/appliance_actions/removal.rb +57 -0
  20. data/lib/cloudkeeper/one/appliance_actions/update.rb +34 -0
  21. data/lib/cloudkeeper/one/appliance_actions/utils/image_download.rb +43 -0
  22. data/lib/cloudkeeper/one/appliance_actions/utils/template_preparation.rb +36 -0
  23. data/lib/cloudkeeper/one/appliance_actions/utils/templates/attributes.erb +23 -0
  24. data/lib/cloudkeeper/one/appliance_actions/utils.rb +10 -0
  25. data/lib/cloudkeeper/one/appliance_actions.rb +11 -0
  26. data/lib/cloudkeeper/one/cli.rb +185 -0
  27. data/lib/cloudkeeper/one/core_connector.rb +106 -0
  28. data/lib/cloudkeeper/one/errors/actions/action_error.rb +9 -0
  29. data/lib/cloudkeeper/one/errors/actions/listing_error.rb +9 -0
  30. data/lib/cloudkeeper/one/errors/actions/registration_error.rb +9 -0
  31. data/lib/cloudkeeper/one/errors/actions/update_error.rb +9 -0
  32. data/lib/cloudkeeper/one/errors/actions.rb +12 -0
  33. data/lib/cloudkeeper/one/errors/argument_error.rb +7 -0
  34. data/lib/cloudkeeper/one/errors/invalid_configuration_error.rb +7 -0
  35. data/lib/cloudkeeper/one/errors/multi_error.rb +25 -0
  36. data/lib/cloudkeeper/one/errors/network_connection_error.rb +7 -0
  37. data/lib/cloudkeeper/one/errors/opennebula/api_call_timeout_error.rb +9 -0
  38. data/lib/cloudkeeper/one/errors/opennebula/authentication_error.rb +9 -0
  39. data/lib/cloudkeeper/one/errors/opennebula/missing_pool_error.rb +9 -0
  40. data/lib/cloudkeeper/one/errors/opennebula/opennebula_error.rb +9 -0
  41. data/lib/cloudkeeper/one/errors/opennebula/resource_not_found_error.rb +9 -0
  42. data/lib/cloudkeeper/one/errors/opennebula/resource_retrieval_error.rb +9 -0
  43. data/lib/cloudkeeper/one/errors/opennebula/resource_state_error.rb +9 -0
  44. data/lib/cloudkeeper/one/errors/opennebula/stub_error.rb +9 -0
  45. data/lib/cloudkeeper/one/errors/opennebula/user_not_authorized_error.rb +9 -0
  46. data/lib/cloudkeeper/one/errors/opennebula.rb +17 -0
  47. data/lib/cloudkeeper/one/errors/standard_error.rb +7 -0
  48. data/lib/cloudkeeper/one/errors.rb +14 -0
  49. data/lib/cloudkeeper/one/opennebula/appliance_handler.rb +91 -0
  50. data/lib/cloudkeeper/one/opennebula/datastore_handler.rb +16 -0
  51. data/lib/cloudkeeper/one/opennebula/group_handler.rb +12 -0
  52. data/lib/cloudkeeper/one/opennebula/handler.rb +59 -0
  53. data/lib/cloudkeeper/one/opennebula/helper.rb +27 -0
  54. data/lib/cloudkeeper/one/opennebula/image_handler.rb +133 -0
  55. data/lib/cloudkeeper/one/opennebula/tags.rb +34 -0
  56. data/lib/cloudkeeper/one/opennebula/template_handler.rb +24 -0
  57. data/lib/cloudkeeper/one/opennebula.rb +14 -0
  58. data/lib/cloudkeeper/one/settings.rb +21 -0
  59. data/lib/cloudkeeper/one/version.rb +5 -0
  60. data/lib/cloudkeeper/one.rb +19 -0
  61. data/lib/cloudkeeper_grpc.rb +5 -0
  62. metadata +385 -0
@@ -0,0 +1,43 @@
1
+ require 'securerandom'
2
+
3
+ module Cloudkeeper
4
+ module One
5
+ module ApplianceActions
6
+ module Utils
7
+ module ImageDownload
8
+ def download_image(uri, username, password)
9
+ logger.debug "Downloading image from #{uri.inspect} (username: #{username}, password: #{password})"
10
+ filename = generate_filename
11
+ retrieve_image URI.parse(uri), username, password, filename
12
+
13
+ logger.debug "Image stored into #{filename}"
14
+ filename
15
+ rescue URI::InvalidURIError => ex
16
+ raise Cloudkeeper::One::Errors::NetworkConnectionError, ex
17
+ end
18
+
19
+ private
20
+
21
+ def retrieve_image(uri, username, password, filename)
22
+ Net::HTTP.start(uri.host, uri.port) do |http|
23
+ request = Net::HTTP::Get.new(uri)
24
+ request.basic_auth username, password
25
+
26
+ http.request(request) do |response|
27
+ response.value
28
+ open(filename, 'w') { |file| response.read_body { |chunk| file.write(chunk) } }
29
+ end
30
+ end
31
+ rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, Errno::ECONNREFUSED, EOFError, Net::HTTPBadResponse,
32
+ Net::HTTPServerException, Net::HTTPHeaderSyntaxError, Net::ProtocolError => ex
33
+ raise Cloudkeeper::One::Errors::NetworkConnectionError, ex
34
+ end
35
+
36
+ def generate_filename
37
+ File.join(Cloudkeeper::One::Settings[:'appliances-tmp-dir'], SecureRandom.uuid)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,36 @@
1
+ require 'erb'
2
+ require 'tilt/erb'
3
+
4
+ module Cloudkeeper
5
+ module One
6
+ module ApplianceActions
7
+ module Utils
8
+ module TemplatePreparation
9
+ def prepare_template(filename, data)
10
+ template_file = File.join(Cloudkeeper::One::Settings[:'appliances-template-dir'], filename)
11
+ raise Cloudkeeper::One::Errors::ArgumentError, "Missing file #{filename.inspect} in template directory" \
12
+ unless File.exist?(template_file)
13
+
14
+ logger.debug "Populating template from #{template_file}"
15
+ templates = [template_file, File.join(File.dirname(__FILE__), 'templates', 'attributes.erb')]
16
+
17
+ data[:image] ||= nil
18
+ rendered = render_templates templates, data
19
+ logger.debug "Template:\n#{rendered}"
20
+ rendered
21
+ end
22
+
23
+ def render_templates(templates, data)
24
+ Tempfile.open 'cloudkeeper-template' do |tmp|
25
+ templates.each { |template| tmp.write(File.read(template)) }
26
+ tmp.flush
27
+
28
+ template = Tilt::ERBTemplate.new tmp
29
+ template.render Object.new, data
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ <%= Cloudkeeper::One::Opennebula::Tags::ID %> = "<%= Cloudkeeper::One::Settings[:identifier] %>"
2
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_ID %> = "<%= appliance.identifier %>"
3
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_TITLE %> = "<%= appliance.title %>"
4
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_DESCRIPTION %> = "<%= appliance.description %>"
5
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_MPURI %> = "<%= appliance.mpuri %>"
6
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_GROUP %> = "<%= appliance.group %>"
7
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_RAM %> = "<%= appliance.ram %>"
8
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_CORE %> = "<%= appliance.core %>"
9
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_VERSION %> = "<%= appliance.version %>"
10
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_ARCHITECTURE %> = "<%= appliance.architecture %>"
11
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_OPERATING_SYSTEM %> = "<%= appliance.operating_system %>"
12
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_VO %> = "<%= appliance.vo %>"
13
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_EXPIRATION_DATE %> = "<%= appliance.expiration_date %>"
14
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_IMAGE_LIST_ID %> = "<%= appliance.image_list_identifier %>"
15
+
16
+ <% if image %>
17
+ <%= Cloudkeeper::One::Opennebula::Tags::IMAGE_URI %> = "<%= image.uri %>"
18
+ <%= Cloudkeeper::One::Opennebula::Tags::IMAGE_CHECKSUM %> = "<%= image.checksum %>"
19
+ <%= Cloudkeeper::One::Opennebula::Tags::IMAGE_SIZE %> = "<%= image.size %>"
20
+ <%= Cloudkeeper::One::Opennebula::Tags::IMAGE_FORMAT %> = "<%= image.format %>"
21
+ <% end %>
22
+
23
+ <%= Cloudkeeper::One::Opennebula::Tags::APPLIANCE_ATTRIBUTES %> = "<%= Base64.strict_encode64 appliance.attributes.to_h.to_json %>"
@@ -0,0 +1,10 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module ApplianceActions
4
+ module Utils
5
+ autoload :ImageDownload, 'cloudkeeper/one/appliance_actions/utils/image_download'
6
+ autoload :TemplatePreparation, 'cloudkeeper/one/appliance_actions/utils/template_preparation'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module ApplianceActions
4
+ autoload :Registration, 'cloudkeeper/one/appliance_actions/registration'
5
+ autoload :Removal, 'cloudkeeper/one/appliance_actions/removal'
6
+ autoload :Update, 'cloudkeeper/one/appliance_actions/update'
7
+ autoload :List, 'cloudkeeper/one/appliance_actions/list'
8
+ autoload :Utils, 'cloudkeeper/one/appliance_actions/utils'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,185 @@
1
+ require 'thor'
2
+ require 'yell'
3
+ require 'chronic_duration'
4
+
5
+ module Cloudkeeper
6
+ module One
7
+ class CLI < Thor
8
+ class_option :'logging-level',
9
+ required: true,
10
+ default: Cloudkeeper::One::Settings['logging']['level'],
11
+ type: :string,
12
+ enum: Yell::Severities
13
+ class_option :'logging-file',
14
+ default: Cloudkeeper::One::Settings['logging']['file'],
15
+ type: :string,
16
+ desc: 'File to write logs to'
17
+ class_option :debug,
18
+ default: Cloudkeeper::One::Settings['debug'],
19
+ type: :boolean,
20
+ desc: 'Runs cloudkeeper in debug mode'
21
+
22
+ method_option :'listen-address',
23
+ required: true,
24
+ default: Cloudkeeper::One::Settings['listen-address'],
25
+ type: :string,
26
+ desc: 'IP address gRPC server will listen on'
27
+ method_option :authentication,
28
+ default: Cloudkeeper::One::Settings['authentication'],
29
+ type: :boolean,
30
+ desc: 'Client <-> server authentication'
31
+ method_option :certificate,
32
+ required: false,
33
+ default: Cloudkeeper::One::Settings['certificate'],
34
+ type: :string,
35
+ desc: "Backend's host certificate"
36
+ method_option :key,
37
+ required: false,
38
+ default: Cloudkeeper::One::Settings['key'],
39
+ type: :string,
40
+ desc: "Backend's host key"
41
+ method_option :identifier,
42
+ required: true,
43
+ default: Cloudkeeper::One::Settings['identifier'],
44
+ type: :string,
45
+ desc: 'Instance identifier'
46
+ method_option :'core-certificate',
47
+ required: false,
48
+ default: Cloudkeeper::One::Settings['core']['certificate'],
49
+ type: :string,
50
+ desc: "Core's certificate"
51
+ method_option :'appliances-tmp-dir',
52
+ required: true,
53
+ default: Cloudkeeper::One::Settings['appliances']['tmp-dir'],
54
+ type: :string,
55
+ desc: 'Directory where to temporarily store appliances'
56
+ method_option :'appliances-template-dir',
57
+ required: false,
58
+ default: Cloudkeeper::One::Settings['appliances']['template-dir'],
59
+ type: :string,
60
+ desc: 'If set, templates within this directory are used to construct images and templates in OpenNebula'
61
+ method_option :'appliances-permissions',
62
+ required: true,
63
+ default: Cloudkeeper::One::Settings['appliances']['permissions'],
64
+ type: :string,
65
+ desc: 'UNIX-like permissions appliances will have within OpenNebula'
66
+ method_option :'opennebula-secret',
67
+ required: true,
68
+ default: Cloudkeeper::One::Settings['opennebula']['secret'],
69
+ type: :string,
70
+ desc: 'OpenNebula authentication secret'
71
+ method_option :'opennebula-endpoint',
72
+ required: true,
73
+ default: Cloudkeeper::One::Settings['opennebula']['endpoint'],
74
+ type: :string,
75
+ desc: 'OpenNebula XML-RPC endpoint'
76
+ method_option :'opennebula-datastores',
77
+ required: true,
78
+ default: Cloudkeeper::One::Settings['opennebula']['datastores'],
79
+ type: :array,
80
+ desc: 'OpenNebula datastores images will be uploaded to'
81
+ method_option :'opennebula-users',
82
+ required: false,
83
+ default: Cloudkeeper::One::Settings['opennebula']['users'],
84
+ type: :array,
85
+ desc: 'Handle only images/templates of specified users'
86
+ method_option :'opennebula-api-call-timeout',
87
+ required: true,
88
+ default: Cloudkeeper::One::Settings['opennebula']['api-call-timeout'],
89
+ type: :string,
90
+ desc: 'How long will cloudkeeper-one wait for image/template operations to finish in OpenNebula'
91
+
92
+ desc 'sync', 'Runs synchronization process'
93
+ def sync
94
+ initialize_sync options
95
+ grpc_server = GRPC::RpcServer.new
96
+ grpc_server.add_http2_port Cloudkeeper::One::Settings[:'listen-address'], credentials
97
+ grpc_server.handle Cloudkeeper::One::CoreConnector
98
+ grpc_server.run_till_terminated
99
+ rescue Interrupt
100
+ grpc_server.stop
101
+ rescue Cloudkeeper::One::Errors::InvalidConfigurationError => ex
102
+ abort ex.message
103
+ end
104
+
105
+ desc 'version', 'Prints cloudkeeper version'
106
+ def version
107
+ $stdout.puts Cloudkeeper::One::VERSION
108
+ end
109
+
110
+ default_task :sync
111
+
112
+ private
113
+
114
+ def initialize_sync(options)
115
+ initialize_configuration options
116
+ validate_configuration!
117
+ initialize_logger
118
+ logger.debug "cloudkeeper-one 'sync' called with parameters: #{Cloudkeeper::One::Settings.to_hash.inspect}"
119
+ end
120
+
121
+ def validate_configuration!
122
+ validate_configuration_group! :authentication,
123
+ [:certificate, :key, :'core-certificate'],
124
+ 'Authentication configuration missing'
125
+ end
126
+
127
+ def validate_configuration_group!(flag, required_options, error_message)
128
+ return unless Cloudkeeper::One::Settings[flag]
129
+
130
+ raise Cloudkeeper::One::Errors::InvalidConfigurationError, error_message unless all_options_available(required_options)
131
+ end
132
+
133
+ def all_options_available(required_options)
134
+ required_options.reduce(true) { |acc, elem| Cloudkeeper::One::Settings[elem] && acc }
135
+ end
136
+
137
+ def credentials
138
+ return :this_port_is_insecure unless Cloudkeeper::One::Settings[:authentication]
139
+
140
+ GRPC::Core::ServerCredentials.new(
141
+ File.read(Cloudkeeper::One::Settings[:'core-certificate']),
142
+ [
143
+ private_key: File.read(Cloudkeeper::One::Settings[:key]),
144
+ cert_chain: File.read(Cloudkeeper::One::Settings[:certificate])
145
+ ],
146
+ true
147
+ )
148
+ end
149
+
150
+ def initialize_configuration(options)
151
+ Cloudkeeper::One::Settings.clear
152
+ Cloudkeeper::One::Settings.merge! options.to_hash
153
+
154
+ gem_dir = File.realdirpath(File.join(File.dirname(__FILE__), '..', '..', '..'))
155
+ Cloudkeeper::One::Settings[:'appliances-template-dir'] = File.join(gem_dir, 'config', 'templates') \
156
+ unless Cloudkeeper::One::Settings[:'appliances-template-dir']
157
+ Cloudkeeper::One::Settings[:'opennebula-api-call-timeout'] = \
158
+ ChronicDuration.parse Cloudkeeper::One::Settings[:'opennebula-api-call-timeout'], keep_zero: true
159
+ end
160
+
161
+ def initialize_logger
162
+ Cloudkeeper::One::Settings[:'logging-level'] = 'DEBUG' if Cloudkeeper::One::Settings[:debug]
163
+
164
+ logging_file = Cloudkeeper::One::Settings[:'logging-file']
165
+ logging_level = Cloudkeeper::One::Settings[:'logging-level']
166
+
167
+ Yell.new :stdout, name: Object, level: logging_level.downcase, format: Yell::DefaultFormat
168
+ Object.send :include, Yell::Loggable
169
+
170
+ setup_file_logger(logging_file) if logging_file
171
+
172
+ logger.debug 'Running in debug mode...'
173
+ end
174
+
175
+ def setup_file_logger(logging_file)
176
+ unless (File.exist?(logging_file) && File.writable?(logging_file)) || File.writable?(File.dirname(logging_file))
177
+ logger.error "File #{logging_file} isn't writable"
178
+ return
179
+ end
180
+
181
+ logger.adapter :file, logging_file
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,106 @@
1
+ module Cloudkeeper
2
+ module One
3
+ class CoreConnector < CloudkeeperGrpc::Communicator::Service
4
+ attr_reader :image_handler, :template_handler, :datastore_handler, :group_handler
5
+
6
+ include Cloudkeeper::One::ApplianceActions::Registration
7
+ include Cloudkeeper::One::ApplianceActions::Removal
8
+ include Cloudkeeper::One::ApplianceActions::Update
9
+ include Cloudkeeper::One::ApplianceActions::List
10
+
11
+ ERRORS = Hash.new(CloudkeeperGrpc::Constants::STATUS_ERROR).update(
12
+ Cloudkeeper::One::Errors::Actions::ListingError => CloudkeeperGrpc::Constants::STATUS_ERROR_APPLIANCE_NOT_FOUND,
13
+ Cloudkeeper::One::Errors::Actions::UpdateError => CloudkeeperGrpc::Constants::STATUS_ERROR_APPLIANCE_NOT_FOUND,
14
+ Cloudkeeper::One::Errors::NetworkConnectionError => CloudkeeperGrpc::Constants::STATUS_ERROR_APPLIANCE_TRANSFER,
15
+ Cloudkeeper::One::Errors::Opennebula::AuthenticationError => CloudkeeperGrpc::Constants::STATUS_ERROR_AUTHENTICATION,
16
+ Cloudkeeper::One::Errors::Opennebula::UserNotAuthorizedError => CloudkeeperGrpc::Constants::STATUS_ERROR_USER_NOT_AUTHORIZED,
17
+ Cloudkeeper::One::Errors::Opennebula::ResourceNotFoundError => CloudkeeperGrpc::Constants::STATUS_ERROR_RESOURCE_NOT_FOUND,
18
+ Cloudkeeper::One::Errors::Actions::RegistrationError => CloudkeeperGrpc::Constants::STATUS_ERROR_RESOURCE_NOT_FOUND,
19
+ Cloudkeeper::One::Errors::Opennebula::ResourceRetrievalError => CloudkeeperGrpc::Constants::STATUS_ERROR_RESOURCE_RETRIEVAL,
20
+ Cloudkeeper::One::Errors::Opennebula::ResourceStateError => CloudkeeperGrpc::Constants::STATUS_ERROR_RESOURCE_STATE,
21
+ Cloudkeeper::One::Errors::Opennebula::ApiCallTimeoutError => CloudkeeperGrpc::Constants::STATUS_ERROR_RESOURCE_STATE
22
+ ).freeze
23
+
24
+ def initialize
25
+ super
26
+
27
+ @image_handler = Cloudkeeper::One::Opennebula::ImageHandler.new
28
+ @template_handler = Cloudkeeper::One::Opennebula::TemplateHandler.new
29
+ @datastore_handler = Cloudkeeper::One::Opennebula::DatastoreHandler.new
30
+ @group_handler = Cloudkeeper::One::Opennebula::GroupHandler.new
31
+ end
32
+
33
+ def pre_action(_empty, call)
34
+ logger.debug 'Running \'pre-action\'...'
35
+ call_backend(call) { remove_expired }
36
+ end
37
+
38
+ def post_action(_empty, call)
39
+ logger.debug 'Running \'post-action\'...'
40
+ call.output_metadata['status'] = 'SUCCESS'
41
+ Google::Protobuf::Empty.new
42
+ end
43
+
44
+ def add_appliance(appliance, call)
45
+ logger.debug "Registering appliance #{appliance.identifier.inspect}"
46
+ call_backend(call) { register_or_update_appliance appliance }
47
+ end
48
+
49
+ def update_appliance(appliance, call)
50
+ logger.debug "Updating appliance #{appliance.identifier.inspect}"
51
+ call_backend(call) { appliance.image ? register_or_update_appliance(appliance) : update_appliance_metadata(appliance) }
52
+ end
53
+
54
+ def remove_appliance(appliance, call)
55
+ logger.debug "Removing appliance #{appliance.identifier.inspect}"
56
+ call_backend(call) { remove_appliance appliance }
57
+ end
58
+
59
+ def remove_image_list(image_list_identifier, call)
60
+ logger.debug "Removing appliances from image list #{image_list_identifier.image_list_identifier.inspect}"
61
+ call_backend(call) { remove_image_list image_list_identifier.image_list_identifier }
62
+ end
63
+
64
+ def image_lists(_empty, call)
65
+ logger.debug 'Retrieving image lists registered in OpenNebula'
66
+ call_backend(call, default_return_value: [], use_return_value: true) { list_image_lists.each }
67
+ end
68
+
69
+ def appliances(image_list_identifier, call)
70
+ logger.debug "Retrieving appliances from image list #{image_list_identifier.image_list_identifier.inspect} " \
71
+ 'registered in OpenNebula'
72
+ call_backend(call, default_return_value: [], use_return_value: true) do
73
+ list_appliances(image_list_identifier.image_list_identifier).each
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def call_backend(call, default_return_value: Google::Protobuf::Empty.new, use_return_value: false)
80
+ raise Cloudkeeper::One::Errors::ArgumentError, 'Error handler was called without a block!' unless block_given?
81
+
82
+ return_value = handle_errors(call) { yield }
83
+ finalize_return_value(return_value, default_return_value, use_return_value)
84
+ end
85
+
86
+ def handle_errors(call)
87
+ return_value = yield
88
+ call.output_metadata[CloudkeeperGrpc::Constants::KEY_STATUS] = CloudkeeperGrpc::Constants::STATUS_SUCCESS
89
+
90
+ return_value
91
+ rescue Cloudkeeper::One::Errors::StandardError => ex
92
+ logger.error "#{ex.class.inspect}: #{ex.message}"
93
+ call.output_metadata[CloudkeeperGrpc::Constants::KEY_STATUS] = ERRORS[ex.class]
94
+ call.output_metadata[CloudkeeperGrpc::Constants::KEY_MESSAGE] = ex.message
95
+
96
+ return_value
97
+ end
98
+
99
+ def finalize_return_value(return_value, default_return_value, use_return_value)
100
+ return_value = use_return_value ? return_value : default_return_value
101
+
102
+ return_value
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Actions
5
+ class ActionError < Cloudkeeper::One::Errors::StandardError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Actions
5
+ class ListingError < ActionError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Actions
5
+ class RegistrationError < ActionError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Actions
5
+ class UpdateError < ActionError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Actions
5
+ autoload :ActionError, 'cloudkeeper/one/errors/actions/action_error'
6
+ autoload :RegistrationError, 'cloudkeeper/one/errors/actions/registration_error'
7
+ autoload :ListingError, 'cloudkeeper/one/errors/actions/listing_error'
8
+ autoload :UpdateError, 'cloudkeeper/one/errors/actions/update_error'
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ class ArgumentError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ class InvalidConfigurationError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ class MultiError < StandardError
5
+ attr_accessor :errors
6
+
7
+ def initialize
8
+ @errors = []
9
+ end
10
+
11
+ def <<(error)
12
+ @errors << error
13
+ end
14
+
15
+ def message
16
+ errors.map(&:message).join('|')
17
+ end
18
+
19
+ def count
20
+ errors.count
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ class NetworkConnectionError < StandardError; end
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ class ApiCallTimeoutError < OpennebulaError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ class AuthenticationError < OpennebulaError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ class MissingPoolError < OpennebulaError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ class OpennebulaError < Cloudkeeper::One::Errors::StandardError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ class ResourceNotFoundError < OpennebulaError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ class ResourceRetrievalError < OpennebulaError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ class ResourceStateError < OpennebulaError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ class StubError < OpennebulaError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ class UserNotAuthorizedError < OpennebulaError; end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ module Opennebula
5
+ autoload :OpennebulaError, 'cloudkeeper/one/errors/opennebula/opennebula_error'
6
+ autoload :StubError, 'cloudkeeper/one/errors/opennebula/stub_error'
7
+ autoload :MissingPoolError, 'cloudkeeper/one/errors/opennebula/missing_pool_error'
8
+ autoload :ApiCallTimeoutError, 'cloudkeeper/one/errors/opennebula/api_call_timeout_error'
9
+ autoload :AuthenticationError, 'cloudkeeper/one/errors/opennebula/authentication_error'
10
+ autoload :ResourceNotFoundError, 'cloudkeeper/one/errors/opennebula/resource_not_found_error'
11
+ autoload :ResourceRetrievalError, 'cloudkeeper/one/errors/opennebula/resource_retrieval_error'
12
+ autoload :ResourceStateError, 'cloudkeeper/one/errors/opennebula/resource_state_error'
13
+ autoload :UserNotAuthorizedError, 'cloudkeeper/one/errors/opennebula/user_not_authorized_error'
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ module Cloudkeeper
2
+ module One
3
+ module Errors
4
+ class StandardError < ::StandardError; end
5
+ end
6
+ end
7
+ end