cloudkeeper 1.3.1 → 1.4.1

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: 8a7b923d81dc5b5f94d50e099e7775f7994d0e8f
4
- data.tar.gz: 551167065e752bbc83ff8c0d4402903a5f70f418
3
+ metadata.gz: 627d7ad80b5656af87fef1d88bdaa35fae85cda3
4
+ data.tar.gz: c4f5fa24ab19bf98e727e9a36be4cf1581b12005
5
5
  SHA512:
6
- metadata.gz: 17d9205bdac272454f9936230096e44058568f94998ff692ca6c6d3a3d5f1c3eb7c27cc785525bc19b0245e36e0bdded83f24dcc07c4551c55110d1d3177815a
7
- data.tar.gz: 9d8ea1adf2e5dccfaf5f55b673d4a494d80269d4536fd64e7c72d79851f900f8abb1b1593b356d72a5d9d442d249162c4ce065d73ca396d8a6a30a50427a6ad9
6
+ metadata.gz: feaefd01329102a82e8739c481c828f4b18df12b572bed7b4f2cde0bf4f864b1cdc5a6215db65a4434530bad569cede8ba04e6f34f5d6e4ad04d0e3394c3d8c6
7
+ data.tar.gz: 7a6c49eb1bbf1db0ffd46f855db2693cd02b292d03dfd5996429b22631bfec0db367d349fd7b5eb60af30ac91d9815ef9d1e2c483c3b562f64b7c69e42fc0448
@@ -28,6 +28,11 @@ Metrics/ClassLength:
28
28
  Exclude:
29
29
  - 'lib/cloudkeeper/cli.rb'
30
30
 
31
+ Metrics/ClassLength:
32
+ Max: 125
33
+ Include:
34
+ - 'lib/cloudkeeper/managers/appliance_manager.rb'
35
+
31
36
  RSpec/MultipleExpectations:
32
37
  Enabled: false
33
38
 
data/README.md CHANGED
@@ -71,50 +71,53 @@ cloudkeeper is run with executable `cloudkeeper`. For further assistance run `cl
71
71
  $ cloudkeeper help sync
72
72
 
73
73
  Usage:
74
- cloudkeeper sync --backend-endpoint=BACKEND-ENDPOINT --formats=one two three --image-dir=IMAGE-DIR --image-lists=one two three --qemu-img-binary=QEMU-IMG-BINARY
74
+ cloudkeeper sync --backend-endpoint=BACKEND-ENDPOINT --external-tools-execution-timeout=N --formats=one two three --image-dir=IMAGE-DIR --image-lists=one two three --qemu-img-binary=QEMU-IMG-BINARY
75
75
 
76
76
  Options:
77
- --image-lists=one two three # List of image lists to sync against
78
- [--ca-dir=CA-DIR] # CA directory
79
- # Default: /etc/grid-security/certificates/
80
- [--authentication], [--no-authentication] # Client <-> server authentication
81
- [--certificate=CERTIFICATE] # Core's host certificate
82
- # Default: /etc/grid-security/hostcert.pem
83
- [--key=KEY] # Core's host key
84
- # Default: /etc/grid-security/hostkey.pem
85
- --image-dir=IMAGE-DIR # Directory to store images to
86
- # Default: /var/spool/cloudkeeper/images/
87
- --qemu-img-binary=QEMU-IMG-BINARY # Path to qemu-img binary (image conversion)
88
- # Default: /usr/bin/qemu-img
89
- [--nginx-binary=NGINX-BINARY] # Path to nginx binary (HTTP server)
90
- # Default: /usr/bin/nginx
91
- [--remote-mode], [--no-remote-mode] # Remote mode starts HTTP server (NGINX) and serves images to backend via HTTP
92
- [--nginx-error-log-file=NGINX-ERROR-LOG-FILE] # NGINX error log file
93
- # Default: /var/log/cloudkeeper/nginx-error.log
94
- [--nginx-access-log-file=NGINX-ACCESS-LOG-FILE] # NGINX access log file
95
- # Default: /var/log/cloudkeeper/nginx-access.log
96
- [--nginx-pid-file=NGINX-PID-FILE] # NGINX pid file
97
- # Default: /var/run/cloudkeeper/nginx.pid
98
- [--nginx-ip-address=NGINX-IP-ADDRESS] # IP address NGINX can listen on
99
- # Default: 127.0.0.1
100
- [--nginx-min-port=N] # Minimal port NGINX can listen on
101
- # Default: 7300
102
- [--nginx-max-port=N] # Maximal port NGINX can listen on
103
- # Default: 7400
104
- --backend-endpoint=BACKEND-ENDPOINT # Backend's gRPC endpoint
105
- # Default: 127.0.0.1:50051
106
- [--backend-certificate=BACKEND-CERTIFICATE] # Backend's certificate
107
- # Default: /etc/grid-security/backendcert.pem
108
- --formats=one two three # List of acceptable formats images can be converted to
109
- # Default: ["qcow2"]
77
+ --image-lists=one two three # List of image lists to sync against
78
+ [--ca-dir=CA-DIR] # CA directory
79
+ # Default: /etc/grid-security/certificates/
80
+ [--authentication], [--no-authentication] # Client <-> server authentication
81
+ [--certificate=CERTIFICATE] # Core's host certificate
82
+ # Default: /etc/grid-security/hostcert.pem
83
+ [--key=KEY] # Core's host key
84
+ # Default: /etc/grid-security/hostkey.pem
85
+ --image-dir=IMAGE-DIR # Directory to store images to
86
+ # Default: /var/spool/cloudkeeper/images/
87
+ --qemu-img-binary=QEMU-IMG-BINARY # Path to qemu-img binary (image conversion)
88
+ # Default: /usr/bin/qemu-img
89
+ [--nginx-binary=NGINX-BINARY] # Path to nginx binary (HTTP server)
90
+ # Default: /usr/bin/nginx
91
+ --external-tools-execution-timeout=N # Timeout for execution of external tools in seconds
92
+ # Default: 600
93
+ [--remote-mode], [--no-remote-mode] # Remote mode starts HTTP server (NGINX) and serves images to backend via HTTP
94
+ [--nginx-error-log-file=NGINX-ERROR-LOG-FILE] # NGINX error log file
95
+ # Default: /var/log/cloudkeeper/nginx-error.log
96
+ [--nginx-access-log-file=NGINX-ACCESS-LOG-FILE] # NGINX access log file
97
+ # Default: /var/log/cloudkeeper/nginx-access.log
98
+ [--nginx-pid-file=NGINX-PID-FILE] # NGINX pid file
99
+ # Default: /var/run/cloudkeeper/nginx.pid
100
+ [--nginx-ip-address=NGINX-IP-ADDRESS] # IP address NGINX can listen on
101
+ # Default: 127.0.0.1
102
+ [--nginx-port=N] # Port NGINX can listen on
103
+ # Default: 50505
104
+ [--nginx-proxy-ip-address=NGINX-PROXY-IP-ADDRESS] # Proxy IP address
105
+ [--nginx-proxy-port=N] # Proxy port
106
+ [--nginx-proxy-ssl], [--no-nginx-proxy-ssl] # Whether proxy will use SSL connection
107
+ --backend-endpoint=BACKEND-ENDPOINT # Backend's gRPC endpoint
108
+ # Default: 127.0.0.1:50051
109
+ [--backend-certificate=BACKEND-CERTIFICATE] # Backend's certificate
110
+ # Default: /etc/grid-security/backendcert.pem
111
+ --formats=one two three # List of acceptable formats images can be converted to
112
+ # Default: ["qcow2"]
110
113
  --logging-level=LOGGING-LEVEL
111
- # Default: ERROR
112
- # Possible values: DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN
113
- [--logging-file=LOGGING-FILE] # File to write logs to
114
- # Default: /var/log/cloudkeeper/cloudkeeper.log
115
- --lock-file=LOCK-FILE # File used to ensure only one running instance of cloudkeeper
116
- # Default: /var/lock/cloudkeeper/cloudkeeper.lock
117
- [--debug], [--no-debug] # Runs cloudkeeper in debug mode
114
+ # Default: ERROR
115
+ # Possible values: DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN
116
+ [--logging-file=LOGGING-FILE] # File to write logs to
117
+ # Default: /var/log/cloudkeeper/cloudkeeper.log
118
+ --lock-file=LOCK-FILE # File used to ensure only one running instance of cloudkeeper
119
+ # Default: /var/lock/cloudkeeper/cloudkeeper.lock
120
+ [--debug], [--no-debug] # Runs cloudkeeper in debug mode
118
121
  ```
119
122
 
120
123
  ## Contributing
@@ -42,12 +42,12 @@ Gem::Specification.new do |spec|
42
42
  spec.add_development_dependency 'vcr', '~> 3.0'
43
43
  spec.add_development_dependency 'webmock', '~> 3.0'
44
44
  spec.add_development_dependency 'diffy', '~> 3.1'
45
- spec.add_development_dependency 'grpc-tools', '~> 1.0'
45
+ spec.add_development_dependency 'grpc-tools', '>= 1.1', '<= 1.2.5'
46
46
 
47
47
  spec.add_runtime_dependency 'thor', '~> 0.19'
48
48
  spec.add_runtime_dependency 'yell', '~> 2.0'
49
49
  spec.add_runtime_dependency 'mixlib-shellout', '~> 2.2'
50
- spec.add_runtime_dependency 'grpc', '~> 1.0'
50
+ spec.add_runtime_dependency 'grpc', '>= 1.1', '<= 1.2.5'
51
51
  spec.add_runtime_dependency 'settingslogic', '~> 2.0'
52
52
  spec.add_runtime_dependency 'zaru', '~> 0.1'
53
53
  spec.add_runtime_dependency 'activesupport', '>= 4.0', '< 6.0'
@@ -5,9 +5,11 @@ cloudkeeper:
5
5
  certificate: /etc/grid-security/hostcert.pem # Core's host certificate
6
6
  key: /etc/grid-security/hostkey.pem # Core's host key
7
7
  image-dir: /var/spool/cloudkeeper/images/ # Directory to store images to
8
- binaries:
9
- qemu-img: /usr/bin/qemu-img # qemu-img binary (image conversion) location
10
- nginx: /usr/bin/nginx # nginx binary (HTTP server) location
8
+ external-tools:
9
+ binaries:
10
+ qemu-img: /usr/bin/qemu-img # qemu-img binary (image conversion) location
11
+ nginx: /usr/bin/nginx # nginx binary (HTTP server) location
12
+ execution-timeout: 600 # timeout for execution of external tools in seconds
11
13
  remote-mode: false # Remote mode starts HTTP server (NGINX) and serves images to backend via HTTP
12
14
  nginx:
13
15
  runtime-dir: /var/run/cloudkeeper/ # Runtime directory for NGINX
@@ -20,22 +20,23 @@ module Cloudkeeper
20
20
  end
21
21
 
22
22
  def add_appliance(appliance)
23
- logger.debug "'add_appliance' gRPC method call"
23
+ logger.debug "'add_appliance' gRPC method call (appliance.identifier: #{appliance.identifier})"
24
24
  manage_appliance appliance, :add_appliance
25
25
  end
26
26
 
27
27
  def update_appliance(appliance)
28
- logger.debug "'update_appliance' gRPC method call"
28
+ logger.debug "'update_appliance' gRPC method call (appliance.identifier: #{appliance.identifier})"
29
29
  manage_appliance appliance, :update_appliance
30
30
  end
31
31
 
32
32
  def remove_appliance(appliance)
33
- logger.debug "'remove_appliance' gRPC method call"
33
+ logger.debug "'remove_appliance' gRPC method call (appliance.identifier: #{appliance.identifier})"
34
+ appliance.image = nil
34
35
  manage_appliance appliance, :remove_appliance
35
36
  end
36
37
 
37
38
  def remove_image_list(image_list_identifier)
38
- logger.debug "'remove_image_list' gRPC method call"
39
+ logger.debug "'remove_image_list' gRPC method call (image_list_identifier: #{image_list_identifier})"
39
40
  handle_errors grpc_client.remove_image_list(
40
41
  CloudkeeperGrpc::ImageListIdentifier.new(image_list_identifier: image_list_identifier),
41
42
  return_op: true
@@ -53,13 +53,18 @@ module Cloudkeeper
53
53
  desc: 'Directory to store images to'
54
54
  method_option :'qemu-img-binary',
55
55
  required: true,
56
- default: Cloudkeeper::Settings['binaries']['qemu-img'],
56
+ default: Cloudkeeper::Settings['external-tools']['binaries']['qemu-img'],
57
57
  type: :string,
58
58
  desc: 'Path to qemu-img binary (image conversion)'
59
59
  method_option :'nginx-binary',
60
- default: Cloudkeeper::Settings['binaries']['nginx'],
60
+ default: Cloudkeeper::Settings['external-tools']['binaries']['nginx'],
61
61
  type: :string,
62
62
  desc: 'Path to nginx binary (HTTP server)'
63
+ method_option :'external-tools-execution-timeout',
64
+ required: true,
65
+ default: Cloudkeeper::Settings['external-tools']['execution-timeout'],
66
+ type: :numeric,
67
+ desc: 'Timeout for execution of external tools in seconds'
63
68
  method_option :'remote-mode',
64
69
  default: Cloudkeeper::Settings['remote-mode'],
65
70
  type: :boolean,
@@ -2,7 +2,7 @@ module Cloudkeeper
2
2
  class CommandExecutioner
3
3
  class << self
4
4
  def execute(*args)
5
- command = Mixlib::ShellOut.new(*args)
5
+ command = Mixlib::ShellOut.new(*args, timeout: Cloudkeeper::Settings[:'external-tools-execution-timeout'])
6
6
  logger.debug "Executing command: #{command.command.inspect}"
7
7
  command.run_command
8
8
 
@@ -54,8 +54,8 @@ module Cloudkeeper
54
54
  appliance_hash[:'dc:title'],
55
55
  appliance_hash[:'dc:description'],
56
56
  appliance_hash[:'ad:group'],
57
- appliance_hash[:'ad:ram_recommended'],
58
- appliance_hash[:'ad:core_recommended'],
57
+ appliance_hash[:'hv:ram_minimum'],
58
+ appliance_hash[:'hv:core_minimum'],
59
59
  appliance_hash[:'hv:version'],
60
60
  appliance_hash[:'sl:arch']
61
61
 
@@ -6,12 +6,6 @@ module Cloudkeeper
6
6
  module Convertable
7
7
  CONVERT_OUTPUT_FORMATS = %i[raw qcow2 vmdk vdi].freeze
8
8
 
9
- def self.convert_output_formats
10
- CONVERT_OUTPUT_FORMATS
11
- end
12
-
13
- FORMAT_REGEX = /^to_(?<format>#{convert_output_formats.join('|')})$/
14
-
15
9
  def self.included(base)
16
10
  raise Cloudkeeper::Errors::Convertables::ConvertabilityError, "#{base.inspect} cannot become a convertable" \
17
11
  unless base.method_defined?(:file) && base.method_defined?(:format)
@@ -19,27 +13,40 @@ module Cloudkeeper
19
13
  super
20
14
  end
21
15
 
16
+ def convert_output_formats
17
+ CONVERT_OUTPUT_FORMATS
18
+ end
19
+
20
+ def format_regex
21
+ /^to_(?<format>#{convert_output_formats.join('|')})$/
22
+ end
23
+
22
24
  def method_missing(method, *arguments, &block)
23
- result = method.to_s.match(FORMAT_REGEX)
24
- return convert(result[:format]) if result && result[:format]
25
+ result = method.to_s.match(format_regex)
26
+ if result && result[:format]
27
+ return self if format.to_sym == result[:format].to_sym
28
+ return convert result[:format]
29
+ end
25
30
 
26
31
  super
27
32
  end
28
33
 
29
34
  def respond_to_missing?(method, *)
30
- method =~ FORMAT_REGEX || super
35
+ method =~ format_regex || super
31
36
  end
32
37
 
33
38
  private
34
39
 
35
40
  def convert(output_format)
36
41
  logger.debug "Converting file #{file.inspect} from #{format.inspect} to #{output_format.inspect}"
37
- return self if output_format.to_sym == format.to_sym
38
42
 
39
43
  converted_file = File.join(File.dirname(file), "#{File.basename(file, '.*')}.#{output_format}")
40
44
  run_convert_command(output_format, converted_file)
41
45
 
42
46
  image_file converted_file, output_format
47
+ rescue Cloudkeeper::Errors::CommandExecutionError => ex
48
+ delete_if_exists converted_file
49
+ raise ex
43
50
  end
44
51
 
45
52
  def run_convert_command(output_format, converted_file)
@@ -57,6 +64,10 @@ module Cloudkeeper
57
64
  Cloudkeeper::Entities::ImageFile.new converted_file, output_format.to_sym,
58
65
  Cloudkeeper::Utils::Checksum.compute(converted_file), false
59
66
  end
67
+
68
+ def delete_if_exists(file)
69
+ File.delete(file) if File.exist?(file.to_s)
70
+ end
60
71
  end
61
72
  end
62
73
  end
@@ -2,11 +2,7 @@ module Cloudkeeper
2
2
  module Entities
3
3
  module Convertables
4
4
  module Ova
5
- CONVERT_OUTPUT_FORMATS = %i[raw qcow2 vdi].freeze
6
-
7
- def self.convert_output_formats
8
- CONVERT_OUTPUT_FORMATS
9
- end
5
+ CONVERT_OUTPUT_FORMATS = %i[raw qcow2 vdi ova].freeze
10
6
 
11
7
  def self.extended(base)
12
8
  raise Cloudkeeper::Errors::Convertables::ConvertabilityError, "#{base.inspect} cannot become OVA convertable" \
@@ -15,12 +11,13 @@ module Cloudkeeper
15
11
  super
16
12
  end
17
13
 
18
- def to_vmdk
19
- image_file(extract_disk, :vmdk)
14
+ def convert_output_formats
15
+ CONVERT_OUTPUT_FORMATS
20
16
  end
21
17
 
22
- def to_ova
23
- self
18
+ def to_vmdk
19
+ logger.debug "Converting file #{file.inspect} from #{format.inspect} to vmdk"
20
+ image_file(extract_disk, :vmdk)
24
21
  end
25
22
 
26
23
  private
@@ -37,8 +34,12 @@ module Cloudkeeper
37
34
  def extract_disk
38
35
  archived_disk = disk_file
39
36
  disk_directory = File.dirname(file)
37
+ extracted_file = File.join(disk_directory, archived_disk)
40
38
  Cloudkeeper::CommandExecutioner.execute('tar', '-x', '-f', file, '-C', disk_directory, archived_disk)
41
- File.join(disk_directory, archived_disk)
39
+ extracted_file
40
+ rescue Cloudkeeper::Errors::CommandExecutionError => ex
41
+ delete_if_exists extracted_file
42
+ raise ex
42
43
  end
43
44
 
44
45
  def archive_files
@@ -39,6 +39,7 @@ module Cloudkeeper
39
39
  def sync_new_image_lists(backend_image_lists)
40
40
  logger.debug 'Registering appliances from new image lists...'
41
41
  add_list = image_list_manager.image_lists.keys - backend_image_lists
42
+ logger.debug "Image lists to register: #{add_list.inspect}"
42
43
  add_list.each do |image_list_identifier|
43
44
  image_list_manager.image_lists[image_list_identifier].appliances.each_value { |appliance| add_appliance appliance }
44
45
  end
@@ -47,6 +48,7 @@ module Cloudkeeper
47
48
  def sync_old_image_lists(backend_image_lists)
48
49
  logger.debug 'Synchronizing registered appliances...'
49
50
  sync_list = image_list_manager.image_lists.keys & backend_image_lists
51
+ logger.debug "Image lists to synchronize: #{sync_list.inspect}"
50
52
  sync_list.each { |image_list_identifier| sync_image_list image_list_identifier }
51
53
  end
52
54
 
@@ -63,18 +65,21 @@ module Cloudkeeper
63
65
  def remove_appliances(backend_appliances, image_list_appliances)
64
66
  logger.debug 'Removing previously registered appliances...'
65
67
  remove_list = backend_appliances.keys - image_list_appliances.keys
66
- remove_list.each { |appliance_identifier| backend_connector.remove_appliance image_list_appliances[appliance_identifier] }
68
+ logger.debug "Appliances to remove: #{remove_list.inspect}"
69
+ remove_list.each { |appliance_identifier| backend_connector.remove_appliance backend_appliances[appliance_identifier] }
67
70
  end
68
71
 
69
72
  def add_appliances(backend_appliances, image_list_appliances)
70
73
  logger.debug 'Registering new appliances...'
71
74
  add_list = image_list_appliances.keys - backend_appliances.keys
75
+ logger.debug "Appliances to register: #{add_list.inspect}"
72
76
  add_list.each { |appliance_identifier| add_appliance image_list_appliances[appliance_identifier] }
73
77
  end
74
78
 
75
79
  def update_appliances(backend_appliances, image_list_appliances)
76
80
  logger.debug 'Updating appliances...'
77
81
  update_list = backend_appliances.keys & image_list_appliances.keys
82
+ logger.debug "Appliances for potential update: #{update_list.inspect}"
78
83
  update_list.each do |appliance_identifier|
79
84
  image_list_appliance = image_list_appliances[appliance_identifier]
80
85
  backend_appliance = backend_appliances[appliance_identifier]
@@ -1,3 +1,3 @@
1
1
  module Cloudkeeper
2
- VERSION = '1.3.1'.freeze
2
+ VERSION = '1.4.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudkeeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Kimle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-26 00:00:00.000000000 Z
11
+ date: 2017-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -168,16 +168,22 @@ dependencies:
168
168
  name: grpc-tools
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - "~>"
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '1.1'
174
+ - - "<="
172
175
  - !ruby/object:Gem::Version
173
- version: '1.0'
176
+ version: 1.2.5
174
177
  type: :development
175
178
  prerelease: false
176
179
  version_requirements: !ruby/object:Gem::Requirement
177
180
  requirements:
178
- - - "~>"
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '1.1'
184
+ - - "<="
179
185
  - !ruby/object:Gem::Version
180
- version: '1.0'
186
+ version: 1.2.5
181
187
  - !ruby/object:Gem::Dependency
182
188
  name: thor
183
189
  requirement: !ruby/object:Gem::Requirement
@@ -224,16 +230,22 @@ dependencies:
224
230
  name: grpc
225
231
  requirement: !ruby/object:Gem::Requirement
226
232
  requirements:
227
- - - "~>"
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: '1.1'
236
+ - - "<="
228
237
  - !ruby/object:Gem::Version
229
- version: '1.0'
238
+ version: 1.2.5
230
239
  type: :runtime
231
240
  prerelease: false
232
241
  version_requirements: !ruby/object:Gem::Requirement
233
242
  requirements:
234
- - - "~>"
243
+ - - ">="
244
+ - !ruby/object:Gem::Version
245
+ version: '1.1'
246
+ - - "<="
235
247
  - !ruby/object:Gem::Version
236
- version: '1.0'
248
+ version: 1.2.5
237
249
  - !ruby/object:Gem::Dependency
238
250
  name: settingslogic
239
251
  requirement: !ruby/object:Gem::Requirement