cloudkeeper-one 1.0.0

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