cloudkeeper 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +61 -0
  6. data/.travis.yml +21 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.txt +17 -0
  10. data/README.md +122 -0
  11. data/Rakefile +17 -0
  12. data/bin/cloudkeeper +5 -0
  13. data/cloudkeeper.gemspec +45 -0
  14. data/config/cloudkeeper.yml +27 -0
  15. data/lib/cloudkeeper.rb +16 -0
  16. data/lib/cloudkeeper/backend_connector.rb +123 -0
  17. data/lib/cloudkeeper/cli.rb +174 -0
  18. data/lib/cloudkeeper/command_executioner.rb +22 -0
  19. data/lib/cloudkeeper/entities.rb +11 -0
  20. data/lib/cloudkeeper/entities/appliance.rb +84 -0
  21. data/lib/cloudkeeper/entities/conversions.rb +48 -0
  22. data/lib/cloudkeeper/entities/convertables.rb +8 -0
  23. data/lib/cloudkeeper/entities/convertables/convertable.rb +63 -0
  24. data/lib/cloudkeeper/entities/convertables/ova.rb +54 -0
  25. data/lib/cloudkeeper/entities/image.rb +40 -0
  26. data/lib/cloudkeeper/entities/image_file.rb +23 -0
  27. data/lib/cloudkeeper/entities/image_formats.rb +7 -0
  28. data/lib/cloudkeeper/entities/image_formats/ova.rb +41 -0
  29. data/lib/cloudkeeper/entities/image_list.rb +84 -0
  30. data/lib/cloudkeeper/errors.rb +20 -0
  31. data/lib/cloudkeeper/errors/appliance.rb +7 -0
  32. data/lib/cloudkeeper/errors/appliance/propagation_error.rb +7 -0
  33. data/lib/cloudkeeper/errors/argument_error.rb +5 -0
  34. data/lib/cloudkeeper/errors/backend_error.rb +5 -0
  35. data/lib/cloudkeeper/errors/command_execution_error.rb +5 -0
  36. data/lib/cloudkeeper/errors/convertables.rb +7 -0
  37. data/lib/cloudkeeper/errors/convertables/convertability_error.rb +7 -0
  38. data/lib/cloudkeeper/errors/image.rb +9 -0
  39. data/lib/cloudkeeper/errors/image/conversion_error.rb +7 -0
  40. data/lib/cloudkeeper/errors/image/download_error.rb +7 -0
  41. data/lib/cloudkeeper/errors/image/format.rb +12 -0
  42. data/lib/cloudkeeper/errors/image/format/no_format_recognized_error.rb +9 -0
  43. data/lib/cloudkeeper/errors/image/format/no_required_format_available_error.rb +9 -0
  44. data/lib/cloudkeeper/errors/image/format/ova.rb +12 -0
  45. data/lib/cloudkeeper/errors/image/format/ova/invalid_archive_error.rb +11 -0
  46. data/lib/cloudkeeper/errors/image/format/ova/ova_format_error.rb +11 -0
  47. data/lib/cloudkeeper/errors/image/format/recognition_error.rb +9 -0
  48. data/lib/cloudkeeper/errors/image_list.rb +9 -0
  49. data/lib/cloudkeeper/errors/image_list/download_error.rb +7 -0
  50. data/lib/cloudkeeper/errors/image_list/retrieval_error.rb +7 -0
  51. data/lib/cloudkeeper/errors/image_list/verification_error.rb +7 -0
  52. data/lib/cloudkeeper/errors/invalid_configuration_error.rb +5 -0
  53. data/lib/cloudkeeper/errors/invalid_url_error.rb +5 -0
  54. data/lib/cloudkeeper/errors/network_connection_error.rb +5 -0
  55. data/lib/cloudkeeper/errors/nginx_error.rb +5 -0
  56. data/lib/cloudkeeper/errors/no_such_file_error.rb +5 -0
  57. data/lib/cloudkeeper/errors/not_implemented_error.rb +5 -0
  58. data/lib/cloudkeeper/errors/parsing.rb +10 -0
  59. data/lib/cloudkeeper/errors/parsing/invalid_appliance_hash_error.rb +7 -0
  60. data/lib/cloudkeeper/errors/parsing/invalid_image_hash_error.rb +7 -0
  61. data/lib/cloudkeeper/errors/parsing/invalid_image_list_hash_error.rb +7 -0
  62. data/lib/cloudkeeper/errors/parsing/parsing_error.rb +7 -0
  63. data/lib/cloudkeeper/errors/permission_denied_error.rb +5 -0
  64. data/lib/cloudkeeper/errors/standard_error.rb +5 -0
  65. data/lib/cloudkeeper/managers.rb +7 -0
  66. data/lib/cloudkeeper/managers/appliance_manager.rb +152 -0
  67. data/lib/cloudkeeper/managers/image_list_manager.rb +88 -0
  68. data/lib/cloudkeeper/managers/image_manager.rb +82 -0
  69. data/lib/cloudkeeper/nginx.rb +5 -0
  70. data/lib/cloudkeeper/nginx/http_server.rb +113 -0
  71. data/lib/cloudkeeper/nginx/templates/nginx.conf.erb +32 -0
  72. data/lib/cloudkeeper/settings.rb +19 -0
  73. data/lib/cloudkeeper/utils.rb +7 -0
  74. data/lib/cloudkeeper/utils/checksum.rb +9 -0
  75. data/lib/cloudkeeper/utils/hash.rb +9 -0
  76. data/lib/cloudkeeper/utils/url.rb +11 -0
  77. data/lib/cloudkeeper/version.rb +3 -0
  78. data/lib/cloudkeeper_grpc.rb +5 -0
  79. metadata +416 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e3b7552e766ed9dff94b3c02ead5b2d7457146d7
4
+ data.tar.gz: 9fc5d03ddd65bd5502b9bbf7cfa716c5e5f17306
5
+ SHA512:
6
+ metadata.gz: 0a9273fe7503544dd2ed1749d577fbf49a8db35a7b6a9dc4f71230109000bf7e302d9b5c8050a955515b105af0dbcb48fc23a8923b06f3f4f9631cce3a020cae
7
+ data.tar.gz: 69ee71cc79f047eeb8efb5a80c512285feca404c2047c178d00d563fc57aab294ba7db8873ece88cf038e966167f466ce295e783d366750801bf7e719ac56eb1
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ example
11
+ /vendor/
12
+ /coverage/
@@ -0,0 +1,3 @@
1
+ [submodule "lib/cloudkeeper_grpc"]
2
+ path = lib/cloudkeeper_grpc
3
+ url = https://github.com/the-cloudkeeper-project/cloudkeeper-grpc-ruby.git
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,61 @@
1
+ require: rubocop-rspec
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.0
5
+ Exclude:
6
+ - 'vendor/**/*'
7
+ - 'lib/cloudkeeper_grpc/*'
8
+
9
+ Metrics/LineLength:
10
+ Max: 135
11
+
12
+ Style/Documentation:
13
+ Enabled: false
14
+
15
+ Metrics/MethodLength:
16
+ Max: 15
17
+ Exclude:
18
+ - 'lib/cloudkeeper/entities/appliance.rb'
19
+ - 'lib/cloudkeeper/nginx/http_server.rb'
20
+
21
+ Metrics/AbcSize:
22
+ Max: 20
23
+ Exclude:
24
+ - 'lib/cloudkeeper/entities/conversions.rb'
25
+
26
+ Metrics/ClassLength:
27
+ Max: 120
28
+ Exclude:
29
+ - 'lib/cloudkeeper/cli.rb'
30
+
31
+ RSpec/MultipleExpectations:
32
+ Enabled: false
33
+
34
+ RSpec/ExampleLength:
35
+ Enabled: false
36
+
37
+ RSpec/NestedGroups:
38
+ Max: 3
39
+
40
+ RSpec/NestedGroups:
41
+ Max: 4
42
+ Include:
43
+ - 'spec/cloudkeeper/backend_connector_spec.rb'
44
+
45
+ RSpec/SubjectStub:
46
+ Exclude:
47
+ - 'spec/cloudkeeper/backend_connector_spec.rb'
48
+
49
+ Metrics/ParameterLists:
50
+ Exclude:
51
+ - 'lib/cloudkeeper/entities/*.rb'
52
+
53
+ Metrics/BlockLength:
54
+ Exclude:
55
+ - 'Rakefile'
56
+ - '**/*.rake'
57
+ - 'spec/**/*.rb'
58
+ - '*.gemspec'
59
+ - 'lib/cloudkeeper/entities/appliance.rb'
60
+ - 'lib/cloudkeeper/entities/image_list.rb'
61
+ - 'lib/cloudkeeper/grpc/*'
@@ -0,0 +1,21 @@
1
+ sudo: false
2
+
3
+ language: ruby
4
+ rvm:
5
+ - ruby-head
6
+ - 2.2.6
7
+ - 2.3.3
8
+ - 2.4.0
9
+
10
+ matrix:
11
+ allow_failures:
12
+ - rvm: ruby-head
13
+ fast_finish: true
14
+
15
+ branches:
16
+ only:
17
+ - master
18
+
19
+ before_install: 'gem install bundler -v 1.13.0'
20
+
21
+ script: 'bundle exec rake acceptance'
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at kimle.michal@gmail.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cloud-keeper.gemspec
4
+ gemspec
@@ -0,0 +1,17 @@
1
+ The work represented by this source file was partially or entirely
2
+ funded by the EGI-Engage project co-funded by the European Union (EU)
3
+ Horizon 2020 program under Grant number 654142.
4
+
5
+ Copyright (c) 2017 CESNET
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
@@ -0,0 +1,122 @@
1
+ # cloudkeeper
2
+ cloudkeeper is an AppDB <-> cloud synchronization utility
3
+
4
+ [![Build Status](https://secure.travis-ci.org/the-cloudkeeper-project/cloudkeeper.png)](http://travis-ci.org/the-cloudkeeper-project/cloudkeeper)
5
+ [![Dependency Status](https://gemnasium.com/the-cloudkeeper-project/cloudkeeper.png)](https://gemnasium.com/the-cloudkeeper-project/cloudkeeper)
6
+ [![Gem Version](https://fury-badge.herokuapp.com/rb/cloudkeeper.png)](https://badge.fury.io/rb/cloudkeeper)
7
+ [![Code Climate](https://codeclimate.com/github/the-cloudkeeper-project/cloudkeeper.png)](https://codeclimate.com/github/the-cloudkeeper-project/cloudkeeper)
8
+
9
+ ## What does cloudkeeper do?
10
+ cloudkeeper is able to read image lists provided by EGI AppDB, parse their content and decide what cloud appliances should be added, updated or removed from managed cloud. During the addition and update cloudkeeper is able to download an appliance's image and convert it to the format supported by the managed cloud.
11
+
12
+ Currently supported image formats are:
13
+ * QCOW2
14
+ * RAW
15
+ * VMDK
16
+ * OVA
17
+
18
+ ## How does cloudkeeper work?
19
+ cloudkeeper communicates with cloud specific components via [gRPC](http://www.grpc.io/) communication framework to manage individual clouds.
20
+
21
+ Currently supported clouds:
22
+ * [OpenNebula](https://opennebula.org/) - component [cloudkeeper-one](https://github.com/the-cloudkeeper-project/cloudkeeper-one)
23
+ * [OpenStack](https://www.openstack.org/) - component [cloudkeeper-os](https://github.com/the-cloudkeeper-project/cloudkeeper-os) (under development)
24
+
25
+ ## Requirements
26
+ * Ruby >= 2.2.0
27
+ * Rubygems
28
+ * qemu-img (image conversion utility)
29
+ * NGINX (optional)
30
+
31
+ ## Installation
32
+
33
+ ### From RubyGems.org
34
+ To install the most recent stable version
35
+ ```bash
36
+ gem install cloudkeeper
37
+ ```
38
+
39
+ ### From source (dev)
40
+ **Installation from source should never be your first choice! Especially, if you are not
41
+ familiar with RVM, Bundler, Rake and other dev tools for Ruby!**
42
+
43
+ **However, if you wish to contribute to our project, this is the right way to start.**
44
+
45
+ To build and install the bleeding edge version from master
46
+
47
+ ```bash
48
+ git clone git://github.com/the-cloudkeeper-project/cloudkeeper.git
49
+ cd cloudkeeper
50
+ gem install bundler
51
+ bundle install
52
+ bundle exec rake spec
53
+ ```
54
+
55
+ ## Configuration
56
+ ### Create a configuration file for cloudkeeper
57
+ Configuration file can be read by cloudkeeper from these
58
+ three locations:
59
+
60
+ * `~/.cloudkeeper/cloudkeeper.yml`
61
+ * `/etc/cloudkeeper/cloudkeeper.yml`
62
+ * `PATH_TO_GEM_DIR/config/cloudkeeper.yml`
63
+
64
+ The default configuration file can be found at the last location
65
+ `PATH_TO_GEM_DIR/config/cloudkeeper.yml`.
66
+
67
+ ## Usage
68
+ cloudkeeper is run with executable `cloudkeeper`. For further assistance run `cloudkeeper help sync`:
69
+ ```bash
70
+ $ cloudkeeper help sync
71
+
72
+ Usage:
73
+ 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
+
75
+ Options:
76
+ --image-lists=one two three # List of image lists to sync against
77
+ [--ca-dir=CA-DIR] # CA directory
78
+ # Default: /etc/grid-security/certificates/
79
+ [--authentication], [--no-authentication] # Client <-> server authentication
80
+ [--certificate=CERTIFICATE] # Core's host certificate
81
+ # Default: /etc/grid-security/hostcert.pem
82
+ [--key=KEY] # Core's host key
83
+ # Default: /etc/grid-security/hostkey.pem
84
+ --image-dir=IMAGE-DIR # Directory to store images to
85
+ # Default: /var/spool/cloudkeeper/images/
86
+ --qemu-img-binary=QEMU-IMG-BINARY # Path to qemu-img binary (image conversion)
87
+ # Default: /usr/bin/qemu-img
88
+ [--nginx-binary=NGINX-BINARY] # Path to nginx binary (HTTP server)
89
+ # Default: /usr/bin/nginx
90
+ [--remote-mode], [--no-remote-mode] # Remote mode starts HTTP server (NGINX) and serves images to backend via HTTP
91
+ [--nginx-error-log-file=NGINX-ERROR-LOG-FILE] # NGINX error log file
92
+ # Default: /var/log/cloudkeeper/nginx-error.log
93
+ [--nginx-access-log-file=NGINX-ACCESS-LOG-FILE] # NGINX access log file
94
+ # Default: /var/log/cloudkeeper/nginx-access.log
95
+ [--nginx-pid-file=NGINX-PID-FILE] # NGINX pid file
96
+ # Default: /var/run/cloudkeeper/nginx.pid
97
+ [--nginx-ip-address=NGINX-IP-ADDRESS] # IP address NGINX can listen on
98
+ # Default: 127.0.0.1
99
+ [--nginx-min-port=N] # Minimal port NGINX can listen on
100
+ # Default: 7300
101
+ [--nginx-max-port=N] # Maximal port NGINX can listen on
102
+ # Default: 7400
103
+ --backend-endpoint=BACKEND-ENDPOINT # Backend's gRPC endpoint
104
+ # Default: 127.0.0.1:50051
105
+ [--backend-certificate=BACKEND-CERTIFICATE] # Backend's certificate
106
+ # Default: /etc/grid-security/backendcert.pem
107
+ --formats=one two three # List of acceptable formats images can be converted to
108
+ # Default: ["qcow2"]
109
+ --logging-level=LOGGING-LEVEL
110
+ # Default: ERROR
111
+ # Possible values: DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN
112
+ [--logging-file=LOGGING-FILE] # File to write logs to
113
+ # Default: /var/log/cloudkeeper/cloudkeeper.log
114
+ [--debug], [--no-debug] # Runs cloudkeeper in debug mode
115
+ ```
116
+
117
+ ## Contributing
118
+ 1. Fork it ( https://github.com/the-cloudkeeper-project/cloudkeeper/fork )
119
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
120
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
121
+ 4. Push to the branch (`git push origin my-new-feature`)
122
+ 5. Create a new Pull Request
@@ -0,0 +1,17 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'rubocop/rake_task'
3
+ require 'bundler/gem_tasks'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new
7
+
8
+ task default: :spec
9
+
10
+ desc 'Run acceptance tests (RSpec + Rubocop)'
11
+ task test: 'acceptance'
12
+
13
+ desc 'Run acceptance tests (RSpec + Rubocop)'
14
+ task :acceptance do |_t|
15
+ Rake::Task['spec'].invoke
16
+ Rake::Task['rubocop'].invoke
17
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'cloudkeeper_grpc'
3
+ require 'cloudkeeper'
4
+
5
+ Cloudkeeper::CLI.start(ARGV)
@@ -0,0 +1,45 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cloudkeeper/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'cloudkeeper'
8
+ spec.version = Cloudkeeper::VERSION
9
+ spec.authors = ['Michal Kimle']
10
+ spec.email = ['kimle.michal@gmail.com']
11
+
12
+ spec.summary = 'Synchronize cloud appliances between AppDB and cloud platforms'
13
+ spec.description = 'Synchronize cloud appliances between AppDB and cloud platforms'
14
+ spec.homepage = 'https://github.com/Misenko/cloudkeeper'
15
+ spec.license = 'Apache License, Version 2.0'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.13'
22
+ spec.add_development_dependency 'rake', '~> 11.2'
23
+ spec.add_development_dependency 'rspec', '~> 3.5'
24
+ spec.add_development_dependency 'rubocop', '~> 0.42'
25
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.7'
26
+ spec.add_development_dependency 'rspec-collection_matchers', '~> 1.1'
27
+ spec.add_development_dependency 'simplecov', '~> 0.12'
28
+ spec.add_development_dependency 'pry', '~> 0.10'
29
+ spec.add_development_dependency 'vcr', '~> 3.0'
30
+ spec.add_development_dependency 'webmock', '~> 2.1'
31
+ spec.add_development_dependency 'diffy', '~> 3.1'
32
+ spec.add_development_dependency 'grpc-tools', '~> 1.0'
33
+
34
+ spec.add_runtime_dependency 'thor', '~> 0.19'
35
+ spec.add_runtime_dependency 'yell', '~> 2.0'
36
+ spec.add_runtime_dependency 'mixlib-shellout', '~> 2.2'
37
+ spec.add_runtime_dependency 'grpc', '~> 1.0'
38
+ spec.add_runtime_dependency 'settingslogic', '~> 2.0'
39
+ spec.add_runtime_dependency 'zaru', '~> 0.1'
40
+ spec.add_runtime_dependency 'activesupport', '~> 4.0'
41
+ spec.add_runtime_dependency 'tilt', '~> 2.0'
42
+ spec.add_runtime_dependency 'faraday', '~> 0.11'
43
+
44
+ spec.required_ruby_version = '>= 2.2.0'
45
+ end
@@ -0,0 +1,27 @@
1
+ cloudkeeper:
2
+ image-lists: # List of image lists to sync against
3
+ ca-dir: /etc/grid-security/certificates/ # CA directory
4
+ authentication: false # core (client) <-> backend (server) authentication (certificate, key and backend-certificate options)
5
+ certificate: /etc/grid-security/hostcert.pem # Core's host certificate
6
+ key: /etc/grid-security/hostkey.pem # Core's host key
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
11
+ remote-mode: false # Remote mode starts HTTP server (NGINX) and serves images to backend via HTTP
12
+ nginx:
13
+ error-log-file: /var/log/cloudkeeper/nginx-error.log # File for NGINX error log
14
+ access-log-file: /var/log/cloudkeeper/nginx-access.log # File for NGINX access log
15
+ pid-file: /var/run/cloudkeeper/nginx.pid # NGINX pid file
16
+ ip-address: 127.0.0.1 # IP address NGINX can listen on
17
+ min-port: 7300 # Minimal port NGINX can listen on
18
+ max-port: 7400 # Maximal port NGINX can listen on
19
+ backend:
20
+ endpoint: 127.0.0.1:50051 # Backend's gRPC endpoint
21
+ certificate: /etc/grid-security/backendcert.pem # Backend's certificate
22
+ formats: # List of acceptable formats images can be converted to
23
+ - qcow2
24
+ logging:
25
+ level: ERROR # Logging level
26
+ file: /var/log/cloudkeeper/cloudkeeper.log # File to write log to. To turn off file logging leave this field empty.
27
+ debug: false # Debug mode
@@ -0,0 +1,16 @@
1
+ require 'active_support/all'
2
+ require 'mixlib/shellout'
3
+
4
+ module Cloudkeeper
5
+ autoload :Settings, 'cloudkeeper/settings'
6
+ autoload :CLI, 'cloudkeeper/cli'
7
+ autoload :Utils, 'cloudkeeper/utils'
8
+ autoload :Nginx, 'cloudkeeper/nginx'
9
+ autoload :CommandExecutioner, 'cloudkeeper/command_executioner'
10
+ autoload :Entities, 'cloudkeeper/entities'
11
+ autoload :Managers, 'cloudkeeper/managers'
12
+ autoload :BackendConnector, 'cloudkeeper/backend_connector'
13
+ autoload :Errors, 'cloudkeeper/errors'
14
+ end
15
+
16
+ require 'cloudkeeper/version'
@@ -0,0 +1,123 @@
1
+ module Cloudkeeper
2
+ class BackendConnector
3
+ include Cloudkeeper::Entities::Conversions
4
+
5
+ attr_reader :grpc_client, :nginx
6
+
7
+ def initialize
8
+ @grpc_client = CloudkeeperGrpc::Communicator::Stub.new(Cloudkeeper::Settings[:'backend-endpoint'], credentials)
9
+ @nginx = Cloudkeeper::Nginx::HttpServer.new
10
+ end
11
+
12
+ def pre_action
13
+ logger.debug "'pre_action' gRPC method call"
14
+ handle_errors grpc_client.pre_action(Google::Protobuf::Empty.new, return_op: true), raise_exception: true
15
+ end
16
+
17
+ def post_action
18
+ logger.debug "'post_action' gRPC method call"
19
+ handle_errors grpc_client.post_action(Google::Protobuf::Empty.new, return_op: true)
20
+ end
21
+
22
+ def add_appliance(appliance)
23
+ logger.debug "'add_appliance' gRPC method call"
24
+ manage_appliance appliance, :add_appliance
25
+ end
26
+
27
+ def update_appliance(appliance)
28
+ logger.debug "'update_appliance' gRPC method call"
29
+ manage_appliance appliance, :update_appliance
30
+ end
31
+
32
+ def remove_appliance(appliance)
33
+ logger.debug "'remove_appliance' gRPC method call"
34
+ manage_appliance appliance, :remove_appliance
35
+ end
36
+
37
+ def remove_image_list(image_list_identifier)
38
+ logger.debug "'remove_image_list' gRPC method call"
39
+ handle_errors grpc_client.remove_image_list(
40
+ CloudkeeperGrpc::ImageListIdentifier.new(image_list_identifier: image_list_identifier),
41
+ return_op: true
42
+ )
43
+ end
44
+
45
+ def image_lists
46
+ logger.debug "'image_lists' gRPC method call"
47
+ handle_errors(grpc_client.image_lists(Google::Protobuf::Empty.new, return_op: true)) do |response|
48
+ response.map(&:image_list_identifier)
49
+ end
50
+ end
51
+
52
+ def appliances(image_list_identifier)
53
+ logger.debug "'appliances' gRPC method call"
54
+ handle_errors(
55
+ grpc_client.appliances(
56
+ CloudkeeperGrpc::ImageListIdentifier.new(image_list_identifier: image_list_identifier),
57
+ return_op: true
58
+ )
59
+ ) do |response|
60
+ response.inject({}) do |acc, elem|
61
+ image = convert_image_proto(elem.image)
62
+ appliance = convert_appliance_proto elem, image
63
+ acc.merge appliance.identifier => appliance
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def credentials
71
+ return :this_channel_is_insecure unless Cloudkeeper::Settings[:authentication]
72
+
73
+ GRPC::Core::ChannelCredentials.new(
74
+ File.read(Cloudkeeper::Settings[:'backend-certificate']),
75
+ File.read(Cloudkeeper::Settings[:key]),
76
+ File.read(Cloudkeeper::Settings[:certificate])
77
+ )
78
+ end
79
+
80
+ def handle_errors(operation, raise_exception: false)
81
+ return_value = operation.execute
82
+ return_value = yield(return_value) if block_given?
83
+ check_status operation.trailing_metadata, raise_exception: raise_exception
84
+
85
+ return_value
86
+ end
87
+
88
+ def check_status(metadata, raise_exception: false)
89
+ return if metadata[CloudkeeperGrpc::Constants::KEY_STATUS] == CloudkeeperGrpc::Constants::STATUS_SUCCESS
90
+
91
+ message = "#{metadata[CloudkeeperGrpc::Constants::KEY_STATUS]}: #{metadata[CloudkeeperGrpc::Constants::KEY_MESSAGE]}"
92
+ logger.error "Backend error: #{message}"
93
+ raise Cloudkeeper::Errors::BackendError, message if raise_exception
94
+ end
95
+
96
+ def set_remote_data(image_proto, access_data)
97
+ image_proto.mode = :REMOTE
98
+ image_proto.location = access_data[:url]
99
+ image_proto.username = access_data[:username]
100
+ image_proto.password = access_data[:password]
101
+ end
102
+
103
+ def prepare_image_proto(image)
104
+ image ? convert_image(image) : nil
105
+ end
106
+
107
+ def manage_appliance(appliance, call)
108
+ image = appliance.image
109
+ image_proto = prepare_image_proto image
110
+
111
+ if Cloudkeeper::Settings[:'remote-mode'] && image
112
+ nginx.start image_proto.location
113
+ set_remote_data image_proto, nginx.access_data
114
+ end
115
+
116
+ handle_errors grpc_client.send(call, convert_appliance(appliance, image_proto), return_op: true)
117
+
118
+ nginx.stop if Cloudkeeper::Settings[:'remote-mode'] && image
119
+ rescue Cloudkeeper::Errors::NginxError, Cloudkeeper::Errors::Image::Format::NoRequiredFormatAvailableError => ex
120
+ raise Cloudkeeper::Errors::Appliance::PropagationError, ex
121
+ end
122
+ end
123
+ end