bosh_cpi 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 77f9ed40e596e15952e7c43452f19682c0e1ea83
4
- data.tar.gz: 9939c9c1db5797ee1311541d2e8d34ab63dc6d14
3
+ metadata.gz: 709fb1fb7802d5480f997bf7d63c42b61aef2733
4
+ data.tar.gz: fe72f9fbfb9d259a9d8b1a8624065f233d21f70f
5
5
  SHA512:
6
- metadata.gz: c889201fd88c6abbbb1cb77b4fc123dc1f49398dff060907f5ed1e9d9c79e6999fd2f94aebeb0a644fcfaeb9cebc094d67557791ded96b03ef358a05f5b4f086
7
- data.tar.gz: 98d595503bd95bb1e477bd7ba47529f675e34d7d574e152276ba9c9147595c629cef76567819a763b0abe7659a5b873da0a6dd3706d5c3d89569eb40e9f43318
6
+ metadata.gz: 103658fa73d06670a6167225b12a2905d6680f73b45aef8d93f763c597296143156b19746a311ae5970ddb9ef6ad50a42144d407a6f5dae95ac8f0b00998f4b0
7
+ data.tar.gz: 98e3ccf062d0ce32c07664f34be7ee38525e897096da0241d3cd63468a943a3d6aede383cb584a9bb3f06709ad900e192c9fb33af89776717e24500b4587fa10
data/lib/bosh/cpi.rb CHANGED
@@ -3,4 +3,5 @@ module Bosh
3
3
  end
4
4
 
5
5
  require 'bosh/cpi/cli'
6
+ require 'bosh/cpi/logger'
6
7
  require 'bosh/cpi/registry_client'
data/lib/bosh/cpi/cli.rb CHANGED
@@ -34,6 +34,7 @@ class Bosh::Cpi::Cli
34
34
  @cpi = cpi
35
35
  @logs_string_io = logs_string_io
36
36
  @result_io = result_io
37
+ @logger = Bosh::Cpi::Logger.new(STDERR)
37
38
  end
38
39
 
39
40
  def run(json)
@@ -62,12 +63,19 @@ class Bosh::Cpi::Cli
62
63
  return error_response(INVALID_CALL_ERROR_TYPE, "Request should include context with director uuid, got: '#{context.inspect}'", false)
63
64
  end
64
65
 
66
+ req_id = context['request_id']
67
+ @logger.set_request_id(req_id)
68
+
65
69
  configure_director(context['director_uuid'])
66
70
 
67
71
  ruby_method = RPC_METHOD_TO_RUBY_METHOD[method] || method
68
72
 
69
73
  begin
74
+ start_time = Time.now.utc
75
+ @logger.info("Starting #{method}...")
76
+
70
77
  cpi = @cpi.call(context)
78
+
71
79
  result = cpi.public_send(ruby_method, *arguments)
72
80
  rescue Bosh::Clouds::RetriableCloudError => e
73
81
  return error_response(error_name(e), e.message, e.ok_to_retry, e.backtrace)
@@ -77,6 +85,9 @@ class Bosh::Cpi::Cli
77
85
  return error_response(INVALID_CALL_ERROR_TYPE, "Arguments are not correct, details: '#{e.message}'", false, e.backtrace)
78
86
  rescue Exception => e
79
87
  return error_response(UNKNOWN_ERROR_TYPE, e.message, false, e.backtrace)
88
+ ensure
89
+ end_time = Time.now.utc
90
+ @logger.info("Finished #{method} in #{(end_time - start_time).round(2)} seconds")
80
91
  end
81
92
 
82
93
  result_response(result)
@@ -0,0 +1,15 @@
1
+ require 'logger'
2
+
3
+ class Bosh::Cpi::Logger < Logger
4
+
5
+ def initialize(log_device)
6
+ super(log_device)
7
+ end
8
+
9
+ def set_request_id(req_id)
10
+ original_formatter = Logger::Formatter.new
11
+ self.formatter = proc { |severity, datetime, progname, msg|
12
+ original_formatter.call(severity, datetime, "[req_id #{req_id}]#{progname}", msg)
13
+ }
14
+ end
15
+ end
data/lib/cloud.rb CHANGED
@@ -6,9 +6,6 @@ require "forwardable"
6
6
 
7
7
  require "cloud/config"
8
8
  require "cloud/errors"
9
- require "cloud/provider"
10
- require "cloud/external_cpi"
11
- require "cloud/internal_cpi"
12
9
 
13
10
  module Bosh
14
11
 
data/lib/cloud/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Clouds
3
- VERSION = '2.0.1'
3
+ VERSION = '0.0.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh_cpi
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - VMware
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-11 00:00:00.000000000 Z
11
+ date: 2016-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bosh_common
14
+ name: membrane
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.3262.24.0
19
+ version: 1.1.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.3262.24.0
26
+ version: 1.1.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: membrane
28
+ name: logging
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.1.0
33
+ version: 1.8.2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.1.0
40
+ version: 1.8.2
41
41
  - !ruby/object:Gem::Dependency
42
- name: logging
42
+ name: httpclient
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 1.8.2
47
+ version: 2.7.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 1.8.2
54
+ version: 2.7.1
55
55
  description: BOSH CPI
56
56
  email: support@cloudfoundry.com
57
57
  executables: []
@@ -62,15 +62,13 @@ files:
62
62
  - lib/bosh/cpi/cli.rb
63
63
  - lib/bosh/cpi/compatibility_helpers.rb
64
64
  - lib/bosh/cpi/compatibility_helpers/delete_vm.rb
65
+ - lib/bosh/cpi/logger.rb
65
66
  - lib/bosh/cpi/registry_client.rb
66
67
  - lib/bosh/cpi/tasks.rb
67
68
  - lib/bosh/cpi/tasks/spec.rake
68
69
  - lib/cloud.rb
69
70
  - lib/cloud/config.rb
70
71
  - lib/cloud/errors.rb
71
- - lib/cloud/external_cpi.rb
72
- - lib/cloud/internal_cpi.rb
73
- - lib/cloud/provider.rb
74
72
  - lib/cloud/version.rb
75
73
  homepage: https://github.com/cloudfoundry/bosh
76
74
  licenses:
@@ -92,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
90
  version: '0'
93
91
  requirements: []
94
92
  rubyforge_project:
95
- rubygems_version: 2.5.1
93
+ rubygems_version: 2.6.4
96
94
  signing_key:
97
95
  specification_version: 4
98
96
  summary: BOSH CPI
@@ -1,163 +0,0 @@
1
- require 'membrane'
2
- require 'open3'
3
-
4
- module Bosh::Clouds
5
- class ExternalCpi
6
- # Raised when the external CPI executable returns an error unknown to director
7
- class UnknownError < StandardError; end
8
-
9
- # Raised when the external CPI executable returns nil or invalid JSON format to director
10
- class InvalidResponse < StandardError; end
11
-
12
- # Raised when the external CPI bin/cpi is not executable
13
- class NonExecutable < StandardError; end
14
-
15
- KNOWN_RPC_ERRORS = %w(
16
- Bosh::Clouds::CpiError
17
- Bosh::Clouds::NotSupported
18
- Bosh::Clouds::NotImplemented
19
-
20
- Bosh::Clouds::CloudError
21
- Bosh::Clouds::VMNotFound
22
-
23
- Bosh::Clouds::NoDiskSpace
24
- Bosh::Clouds::DiskNotAttached
25
- Bosh::Clouds::DiskNotFound
26
- Bosh::Clouds::VMCreationFailed
27
- ).freeze
28
-
29
- RESPONSE_SCHEMA = Membrane::SchemaParser.parse do
30
- {
31
- 'result' => any,
32
- 'error' => enum(nil,
33
- { 'type' => String,
34
- 'message' => String,
35
- 'ok_to_retry' => bool
36
- }
37
- ),
38
- 'log' => String
39
- }
40
- end
41
-
42
- def initialize(cpi_path, director_uuid, properties_from_cpi_config = nil)
43
- @cpi_path = cpi_path
44
- @director_uuid = director_uuid
45
- @logger = Config.logger
46
- @properties_from_cpi_config = properties_from_cpi_config
47
- end
48
-
49
- def current_vm_id(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
50
- def create_stemcell(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
51
- def delete_stemcell(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
52
- def create_vm(*arguments) invoke_cpi_method(__method__.to_s, *arguments); end
53
- def delete_vm(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
54
- def has_vm?(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
55
- def reboot_vm(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
56
- def set_vm_metadata(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
57
- def create_disk(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
58
- def has_disk?(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
59
- def delete_disk(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
60
- def attach_disk(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
61
- def detach_disk(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
62
- def snapshot_disk(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
63
- def delete_snapshot(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
64
- def get_disks(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
65
- def ping(*arguments); invoke_cpi_method(__method__.to_s, *arguments); end
66
-
67
- private
68
-
69
- def invoke_cpi_method(method_name, *arguments)
70
- context = {
71
- 'director_uuid' => @director_uuid
72
- }
73
- context.merge!(@properties_from_cpi_config) unless @properties_from_cpi_config.nil?
74
-
75
- request = request_json(method_name, arguments, context)
76
- redacted_request = request_json(method_name, arguments, redact_context(context))
77
-
78
- env = {'PATH' => '/usr/sbin:/usr/bin:/sbin:/bin', 'TMPDIR' => ENV['TMPDIR']}
79
- cpi_exec_path = checked_cpi_exec_path
80
-
81
- @logger.debug("External CPI sending request: #{redacted_request} with command: #{cpi_exec_path}")
82
- cpi_response, stderr, exit_status = Open3.capture3(env, cpi_exec_path, stdin_data: request, unsetenv_others: true)
83
- @logger.debug("External CPI got response: #{cpi_response}, err: #{stderr}, exit_status: #{exit_status}")
84
-
85
- parsed_response = parsed_response(cpi_response)
86
- validate_response(parsed_response)
87
-
88
- if parsed_response['error']
89
- handle_error(parsed_response['error'], method_name)
90
- end
91
-
92
- save_cpi_log(parsed_response['log'])
93
- save_cpi_log(stderr)
94
-
95
- parsed_response['result']
96
- end
97
-
98
- def checked_cpi_exec_path
99
- unless File.executable?(@cpi_path)
100
- raise NonExecutable, "Failed to run cpi: '#{@cpi_path}' is not executable"
101
- end
102
- @cpi_path
103
- end
104
-
105
- def redact_context(context)
106
- return context if @properties_from_cpi_config.nil?
107
- Hash[context.map{|k,v|[k,@properties_from_cpi_config.keys.include?(k) ? '<redacted>' : v]}]
108
- end
109
-
110
- def request_json(method_name, arguments, context)
111
- JSON.dump({
112
- 'method' => method_name.gsub(/\?$/,''),
113
- 'arguments' => arguments,
114
- 'context' => context
115
- })
116
- end
117
-
118
- def handle_error(error_response, method_name)
119
- error_type = error_response['type']
120
- error_message = error_response['message']
121
- unless KNOWN_RPC_ERRORS.include?(error_type)
122
- raise UnknownError, "Unknown CPI error '#{error_type}' with message '#{error_message}' in '#{method_name}' CPI method"
123
- end
124
-
125
- error_class = constantize(error_type)
126
-
127
- if error_class <= RetriableCloudError
128
- error = error_class.new(error_response['ok_to_retry'])
129
- else
130
- error = error_class.new(error_message)
131
- end
132
-
133
- raise error, "CPI error '#{error_type}' with message '#{error_message}' in '#{method_name}' CPI method"
134
- end
135
-
136
- def save_cpi_log(output)
137
- # cpi log path is set up at the beginning of every task in Config
138
- # see JobRunner#setup_task_logging
139
- File.open(Config.cpi_task_log, 'a') do |f|
140
- f.write(output)
141
- end
142
- end
143
-
144
- def parsed_response(input)
145
- begin
146
- JSON.load(input)
147
- rescue JSON::ParserError => e
148
- raise InvalidResponse, "Invalid CPI response - ParserError - #{e.message}"
149
- end
150
- end
151
-
152
- def validate_response(response)
153
- RESPONSE_SCHEMA.validate(response)
154
- rescue Membrane::SchemaValidationError => e
155
- raise InvalidResponse, "Invalid CPI response - SchemaValidationError: #{e.message}"
156
- end
157
-
158
- def constantize(camel_cased_word)
159
- error_name = camel_cased_word.split('::').last
160
- Bosh::Clouds.const_get(error_name)
161
- end
162
- end
163
- end
@@ -1,25 +0,0 @@
1
- module Bosh::Clouds
2
- class InternalCpi
3
- def initialize(cloud)
4
- @cloud = cloud
5
- end
6
-
7
- private
8
-
9
- def method_missing(method_sym, *arguments, &block)
10
- invoke_cpi_method(method_sym, arguments)
11
- end
12
-
13
- def respond_to?(method_sym)
14
- cloud.respond_to?(method_sym)
15
- end
16
-
17
- def cloud
18
- @cloud
19
- end
20
-
21
- def invoke_cpi_method(method_sym, arguments)
22
- cloud.send(method_sym, *JSON.parse(JSON.dump(arguments)))
23
- end
24
- end
25
- end
@@ -1,31 +0,0 @@
1
- module Bosh::Clouds
2
- class Provider
3
- def self.create(cloud_config, director_uuid)
4
- if cloud_config.has_key?('provider')
5
- ExternalCpiProvider.create(cloud_config['provider']['path'], director_uuid)
6
- else
7
- InternalCpiProvider.create(cloud_config['plugin'], cloud_config['properties'])
8
- end
9
- end
10
- end
11
-
12
- private
13
-
14
- class InternalCpiProvider
15
- def self.create(plugin, options)
16
- begin
17
- require "cloud/#{plugin}"
18
- rescue LoadError => error
19
- raise CloudError, "Could not load Cloud Provider Plugin: #{plugin}, with error #{error.inspect}"
20
- end
21
-
22
- InternalCpi.new(Bosh::Clouds.const_get(plugin.capitalize).new(options))
23
- end
24
- end
25
-
26
- class ExternalCpiProvider
27
- def self.create(cpi_job_path, director_uuid)
28
- ExternalCpi.new(cpi_job_path, director_uuid)
29
- end
30
- end
31
- end