bosh_cpi 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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