nifty 0.0.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +79 -12
- data/bin/nifty +2 -0
- data/config/nifty.yml +18 -0
- data/config/templates/image.erb +38 -0
- data/config/templates/template.erb +26 -0
- data/lib/nifty/backend.rb +55 -0
- data/lib/nifty/backends/opennebula.rb +109 -0
- data/lib/nifty/backends/utils/opennebula/datastore_handler.rb +36 -0
- data/lib/nifty/backends/utils/opennebula/group_handler.rb +23 -0
- data/lib/nifty/backends/utils/opennebula/handler.rb +60 -0
- data/lib/nifty/backends/utils/opennebula/helper.rb +44 -0
- data/lib/nifty/backends/utils/opennebula/image_handler.rb +209 -0
- data/lib/nifty/backends/utils/opennebula/template_handler.rb +91 -0
- data/lib/nifty/backends/utils/opennebula.rb +9 -0
- data/lib/nifty/backends/utils.rb +2 -0
- data/lib/nifty/backends.rb +5 -0
- data/lib/nifty/command_executioner.rb +202 -0
- data/lib/nifty/errors/api_call_timeout_error.rb +1 -0
- data/lib/nifty/errors/argument_error.rb +1 -0
- data/lib/nifty/errors/backend_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/authentication_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/resource_not_found_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/resource_retrieval_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/resource_state_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/stub_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula/user_not_authorized_error.rb +1 -0
- data/lib/nifty/errors/backends/opennebula.rb +5 -0
- data/lib/nifty/errors/backends/opennebula_error.rb +1 -0
- data/lib/nifty/errors/backends.rb +4 -0
- data/lib/nifty/errors/command_execution_error.rb +1 -0
- data/lib/nifty/errors/event/converter_error.rb +1 -0
- data/lib/nifty/errors/event/loader_error.rb +1 -0
- data/lib/nifty/errors/event.rb +5 -0
- data/lib/nifty/errors/events/event_error.rb +1 -0
- data/lib/nifty/errors/events/expiration_event_error.rb +1 -0
- data/lib/nifty/errors/events/registration_event_error.rb +1 -0
- data/lib/nifty/errors/events.rb +4 -0
- data/lib/nifty/errors/standard_error.rb +1 -0
- data/lib/nifty/errors/transfer_method_error.rb +1 -0
- data/lib/nifty/errors/transfer_methods/destination_not_directory_error.rb +1 -0
- data/lib/nifty/errors/transfer_methods/destination_not_writable_error.rb +1 -0
- data/lib/nifty/errors/transfer_methods/image_file_not_readable_error.rb +1 -0
- data/lib/nifty/errors/transfer_methods.rb +4 -0
- data/lib/nifty/errors.rb +10 -0
- data/lib/nifty/event/converter.rb +29 -0
- data/lib/nifty/event/loader.rb +27 -0
- data/lib/nifty/event/processor.rb +96 -0
- data/lib/nifty/event.rb +6 -0
- data/lib/nifty/events/event.rb +32 -0
- data/lib/nifty/events/opennebula/event.rb +23 -0
- data/lib/nifty/events/opennebula/expiration_event.rb +32 -0
- data/lib/nifty/events/opennebula/metadata_update_event.rb +12 -0
- data/lib/nifty/events/opennebula/registration_event.rb +113 -0
- data/lib/nifty/events/opennebula/utils/events_common.rb +69 -0
- data/lib/nifty/events/opennebula/utils.rb +4 -0
- data/lib/nifty/events/opennebula.rb +6 -0
- data/lib/nifty/events.rb +5 -0
- data/lib/nifty/exit_codes.rb +8 -0
- data/lib/nifty/settings.rb +18 -0
- data/lib/nifty/transfer_method.rb +69 -0
- data/lib/nifty/transfer_methods/opennebula/cp.rb +52 -0
- data/lib/nifty/transfer_methods/opennebula/noop.rb +27 -0
- data/lib/nifty/transfer_methods/opennebula.rb +4 -0
- data/lib/nifty/transfer_methods.rb +4 -0
- data/lib/nifty/version.rb +1 -1
- data/lib/nifty.rb +20 -2
- data/nifty.gemspec +7 -0
- data/schema/appliance.json +295 -0
- data/templates/image.erb +8 -0
- data/templates/template.erb +13 -0
- metadata +166 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34535f6d35b3c8a655fd2e09ba345bed53776e33
|
4
|
+
data.tar.gz: 3da0882d184d3100c510ad0586c0b38c8adb9b7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fdaeac11c89d829767d745b7e33f5290cf02bd9a243fd24a637303d8c8bf79270d94a8a8b5f64236bfa444ca0463c6396eca4ca6c6356bcbc54afc890578c532
|
7
|
+
data.tar.gz: a6d550cf0e9c89b9bfebe07c971892bdee2af05c3479485c33fa0d4597df41839ebdb84d01c10bb9f0ea0b31e8af6eba4f4583d798f1e9be222f964536b065f7
|
data/README.md
CHANGED
@@ -2,17 +2,33 @@
|
|
2
2
|
|
3
3
|
NIFTY is a tool for uploading and registering cloud appliances in OpenNebula.
|
4
4
|
|
5
|
-
[![Build Status](https://secure.travis-ci.org/
|
6
|
-
[![Dependency Status](https://gemnasium.com/
|
5
|
+
[![Build Status](https://secure.travis-ci.org/CESNET/nifty.png)](http://travis-ci.org/CESNET/nifty)
|
6
|
+
[![Dependency Status](https://gemnasium.com/CESNET/nifty.png)](https://gemnasium.com/CESNET/nifty)
|
7
7
|
[![Gem Version](https://fury-badge.herokuapp.com/rb/nifty.png)](https://badge.fury.io/rb/nifty)
|
8
|
-
[![Code Climate](https://codeclimate.com/github/
|
8
|
+
[![Code Climate](https://codeclimate.com/github/CESNET/nifty.png)](https://codeclimate.com/github/CESNET/nifty)
|
9
|
+
|
10
|
+
##What does NIFY do?
|
11
|
+
Basically NIFTY takes a prepared appliance (virtual machine) and its descriptor and automatically uploads, register and prepares template in OpenNebula. Virtual machine can be than easily instantiated. Furthermore, NIFTY can expire an appliance so users will no longer be able to use it (for example due to security reasons). Expired appliances are automatically cleaned after configured time period.
|
12
|
+
|
13
|
+
##How does NIFTY work?
|
14
|
+
NIFTY cooperates with two other tools [COMFY](https://github.com/CESNET/comfy) and [ITCHY](https://github.com/CESNET/itchy) which can prepare an appliance with a correct descriptor. NIFTY then reads a descriptor and either registers or expires the appliance.
|
9
15
|
|
10
16
|
##Requirements
|
11
17
|
* Ruby >= 1.9.3
|
12
18
|
* Rubygems
|
13
19
|
|
20
|
+
###OpenNebula backend
|
21
|
+
* [OpenNebula](http://opennebula.org/) >= 4.6 (doesn't have to be present on the same machine)
|
22
|
+
|
14
23
|
## Installation
|
15
|
-
|
24
|
+
###From distribution specific packages
|
25
|
+
Omnibus packaging for NIFTY will be available soon. Meanwhile, use one of other installation methods.
|
26
|
+
|
27
|
+
###From RubyGems.org
|
28
|
+
To install the most recent stable version
|
29
|
+
```bash
|
30
|
+
gem install nifty
|
31
|
+
```
|
16
32
|
|
17
33
|
###From source (dev)
|
18
34
|
**Installation from source should never be your first choice! Especially, if you are not
|
@@ -23,7 +39,7 @@ familiar with RVM, Bundler, Rake and other dev tools for Ruby!**
|
|
23
39
|
To build and install the bleeding edge version from master
|
24
40
|
|
25
41
|
```bash
|
26
|
-
git clone git://github.com/
|
42
|
+
git clone git://github.com/CESNET/nifty.git
|
27
43
|
cd nifty
|
28
44
|
gem install bundler
|
29
45
|
bundle install
|
@@ -35,18 +51,69 @@ bundle exec rake spec
|
|
35
51
|
Configuration file can be read by NIFTY from these
|
36
52
|
three locations:
|
37
53
|
|
38
|
-
* `~/.nifty/
|
39
|
-
* `/etc/nifty/
|
40
|
-
* `PATH_TO_GEM_DIR/config/
|
54
|
+
* `~/.nifty/nifty.yml`
|
55
|
+
* `/etc/nifty/nifty.yml`
|
56
|
+
* `PATH_TO_GEM_DIR/config/nifty.yml`
|
41
57
|
|
42
58
|
The example configuration file can be found at the last location
|
43
|
-
`PATH_TO_GEM_DIR/config/
|
59
|
+
`PATH_TO_GEM_DIR/config/nifty.yml`.
|
60
|
+
|
61
|
+
##Usage
|
62
|
+
NIFTY is run with executable `nifty`. For further assistance run `nifty help`:
|
63
|
+
```bash
|
64
|
+
$ nifty help
|
65
|
+
|
66
|
+
Commands:
|
67
|
+
nifty backends # Lists all available backends with their description
|
68
|
+
nifty help [COMMAND] # Describe available commands or one specific command
|
69
|
+
nifty opennebula --expiration-interval=EXPIRATION-INTERVAL -d, --datastores=one two three # Runs NIFTY with backend opennebula
|
70
|
+
nifty opennebula-transfer-methods # Lists all available transfer methods with their description for opennebula backend
|
71
|
+
nifty version # Prints NIFTY's version
|
72
|
+
|
73
|
+
Options:
|
74
|
+
-a, --appliance-dir=APPLIANCE-DIR # Directory from where appliance descriptors will be loaded
|
75
|
+
-m, --transfer-method=TRANSFER-METHOD # Transfer method for image upload
|
76
|
+
-t, [--transfer-destination=TRANSFER-DESTINATION] # Image upload destination
|
77
|
+
--logging-level=LOGGING-LEVEL
|
78
|
+
[--logging-file=LOGGING-FILE] # File to write log to
|
79
|
+
[--debug], [--no-debug] # Runs nifty in debug mode
|
80
|
+
```
|
81
|
+
|
82
|
+
###Backends
|
83
|
+
OpenNebula is currently the only supported backend for NIFTY. NIFTY can upload and register images and create VM templates in OpenNebula. Image and template generating mechanism can be customized by providing custom templates via `--template-dir` option. Default templates are situated in `PATH_TO_GEM_DIR/config/templates` directory. To list all options for Opennebula backend run `nifty help opennebula`:
|
84
|
+
```bash
|
85
|
+
$ nifty help opennebula
|
86
|
+
|
87
|
+
Usage:
|
88
|
+
nifty opennebula --expiration-interval=EXPIRATION-INTERVAL -d, --datastores=one two three
|
89
|
+
|
90
|
+
Options:
|
91
|
+
[--secret=SECRET] # Pair of username and password in form of 'username:password' for accessing OpenNebula
|
92
|
+
[--endpoint=ENDPOINT] # OpenNebula's XML RPC endpoint
|
93
|
+
--expiration-interval=EXPIRATION-INTERVAL # How long should expired images be kept in OpenNebula befor removal, 0 means don't remove
|
94
|
+
-d, --datastores=one two three # Names of OpenNebula datastores images will be uploaded to
|
95
|
+
[--template-dir=TEMPLATE-DIR] # If set, templates within this directory are used to construct images and templates in OpenNebula
|
96
|
+
[--description-naming], [--no-description-naming] # If true, uses identifier and version from appliance description as template/image name instead of generated uuids
|
97
|
+
[--disk-expiration], [--no-disk-expiration] # Will expire old disks before the new one is registered
|
98
|
+
--permissions=PERMISSIONS # UNIX-like image and template permissions in OpenNebula
|
99
|
+
-a, --appliance-dir=APPLIANCE-DIR # Directory from where appliance descriptors will be loaded
|
100
|
+
-m, --transfer-method=TRANSFER-METHOD # Transfer method for image upload
|
101
|
+
-t, [--transfer-destination=TRANSFER-DESTINATION] # Image upload destination
|
102
|
+
-b, --backend=BACKEND # Backend for registering images
|
103
|
+
--logging-level=LOGGING-LEVEL
|
104
|
+
[--logging-file=LOGGING-FILE] # File to write log to
|
105
|
+
[--debug], [--no-debug] # Runs nifty in debug mode
|
106
|
+
```
|
107
|
+
|
108
|
+
###Transfer methods
|
109
|
+
NIFTY currently supports two transfer methods:
|
110
|
+
* `noop` (no operation) - dummy transfer method, doesn't change image location
|
111
|
+
* `cp` (copy) - creates an image copy in `--transfer-destination` directory
|
44
112
|
|
45
|
-
|
46
|
-
NIFTY is run with executable `nifty`.
|
113
|
+
To list all available transfer methods for selected backend run `nifty <BACKEND>-transfer-methods`, for example `nifty opennebula-transfer-methods`.
|
47
114
|
|
48
115
|
## Contributing
|
49
|
-
1. Fork it ( https://github.com/
|
116
|
+
1. Fork it ( https://github.com/CESNET/nifty/fork )
|
50
117
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
51
118
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
52
119
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/bin/nifty
CHANGED
data/config/nifty.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
production:
|
2
|
+
appliance-dir: /var/run/nifty/appliances # Directory from where appliance descriptors will be loaded.
|
3
|
+
transfer:
|
4
|
+
method: noop # Transfer method for image upload. Available methods can be listed in help.
|
5
|
+
destination: # Image upload destination. Format depends on transfer method.
|
6
|
+
opennebula:
|
7
|
+
secret: oneadmin:opennebula # If not specified, looking for secret in environment variable ONE_AUTH and file ~/.one/one_auth
|
8
|
+
endpoint: http://localhost:2633/RPC2 # If not specified, looking for endpoint in environment variable ONE_XMLRPC and file ~/.one/one_endpoint
|
9
|
+
datastores: # Array of names of OpenNebula datastores images will be uploaded to. Has to contain at least one datastore if opennebula backend is selected
|
10
|
+
expiration-interval: 2w # How long should expired images be kept in OpenNebula before removal, 0 means don't remove
|
11
|
+
template-dir: # If set, templates within this directory are used to construct images and templates in OpenNebula
|
12
|
+
description-naming: false # If true, uses identifier and version from appliance description as template/image name instead of generated uuids
|
13
|
+
disk-expiration: true # Will expire old disks before the new one is registered
|
14
|
+
permissions: "640" # UNIX-like image and template permissions in OpenNebula, MUST be a string
|
15
|
+
logging:
|
16
|
+
level: ERROR # Logging level
|
17
|
+
file: /var/log/nifty/nifty.log # File to write log to. To turn off file logging leave this field empty.
|
18
|
+
debug: false # Debug mode
|
@@ -0,0 +1,38 @@
|
|
1
|
+
NAME = "<%= name %>"
|
2
|
+
|
3
|
+
<% if appliance.title && appliance.description %>
|
4
|
+
DESCRIPTION = "<%= "#{appliance.title} - #{appliance.description} created using NIFTY on #{::DateTime.now.readable_inspect}." %>"
|
5
|
+
<% else %>
|
6
|
+
DESCRIPTION = "<%= "Image created using NIFTY on #{::DateTime.now.readable_inspect}." %>"
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% case disk.type.upcase %>
|
10
|
+
<% when "CDROM" %>
|
11
|
+
TYPE = "CDROM"
|
12
|
+
DISK_TYPE = "CDROM"
|
13
|
+
PATH = "<%= disk.path %>"
|
14
|
+
<% when "FILE" %>
|
15
|
+
TYPE = "FILE"
|
16
|
+
DISK_TYPE = "FILE"
|
17
|
+
PATH = "<%= disk.path %>"
|
18
|
+
<% else %>
|
19
|
+
TYPE = "OS"
|
20
|
+
DISK_TYPE = "BLOCK"
|
21
|
+
PATH = "<%= disk.path %>"
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<% if disk.device_prefix %>
|
25
|
+
DEV_PREFIX = "<%= disk.device_prefix %>"
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<% if disk.target %>
|
29
|
+
BUS = "<%= disk.target %>"
|
30
|
+
<% end %>
|
31
|
+
|
32
|
+
<% if disk.format %>
|
33
|
+
DRIVER = "<%= disk.format %>"
|
34
|
+
<% end %>
|
35
|
+
|
36
|
+
<% appliance.attributes.each do |key, value| %>
|
37
|
+
<%= key %> = "<%= value %>"
|
38
|
+
<% end %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
NAME = "<%= name %>"
|
2
|
+
|
3
|
+
<% if appliance.title && appliance.description %>
|
4
|
+
DESCRIPTION = "<%= "#{appliance.title} - #{appliance.description} created using NIFTY on #{::DateTime.now.readable_inspect}." %>"
|
5
|
+
<% else %>
|
6
|
+
DESCRIPTION = "<%= "Template created using NIFTY on #{::DateTime.now.readable_inspect}." %>"
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
MEMORY = "<%= appliance.memory || 1024 %>"
|
10
|
+
CPU = "<%= appliance.cpu || 0.25 %>"
|
11
|
+
VCPU = "<%= appliance.cpu || 1 %>"
|
12
|
+
|
13
|
+
OS = [
|
14
|
+
ARCH = "<%= appliance.os.arch || "x86_64" %>"
|
15
|
+
]
|
16
|
+
|
17
|
+
<% disk_names.each do |name| %>
|
18
|
+
DISK = [
|
19
|
+
IMAGE = "<%= name %>",
|
20
|
+
IMAGE_UNAME = "<%= username %>"
|
21
|
+
]
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<% appliance.attributes.each do |key, value| %>
|
25
|
+
<%= key %> = "<%= value %>"
|
26
|
+
<% end %>
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Abstract class for all NIFTY backends
|
2
|
+
#
|
3
|
+
# @author Michal Kimle
|
4
|
+
class Nifty::Backend
|
5
|
+
class << self
|
6
|
+
# Helper method to recognize NIFTY backend
|
7
|
+
#
|
8
|
+
# @return [TrueClass, FalseClass] whether or not class is a NIFTY backend
|
9
|
+
def backend?
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns textual description of the backend
|
14
|
+
# Used in help messages.
|
15
|
+
#
|
16
|
+
# @abstract
|
17
|
+
# @return [String, nil] textual description of the backend
|
18
|
+
def description
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns hash from which new CLI command for backend is constructed
|
23
|
+
#
|
24
|
+
# @abstract
|
25
|
+
# @return [Hash, nil] hash from which new CLI command for backend is constructed
|
26
|
+
def options
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Routine run before any events are processed
|
31
|
+
#
|
32
|
+
# @abstract
|
33
|
+
# @param [Hash] parameters to run pre method with
|
34
|
+
def pre(parameters)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Routine run after all the events are processed
|
38
|
+
#
|
39
|
+
# @abstract
|
40
|
+
# @param [Hash] parameters to run post method with
|
41
|
+
def post(parameters)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Creates specific event for the backend
|
45
|
+
#
|
46
|
+
# @abstract
|
47
|
+
# @param [Nifty::Events::Event] event_class class object representing event
|
48
|
+
# @param [Cloud::Appliance::Descriptor::Appliance] appliance description
|
49
|
+
# @param [Nifty::TransferMethod] transfer_method instance of transfer method used in the event
|
50
|
+
# @param [Hash] parameters any additional parameters
|
51
|
+
# @return [Nifty::Events::Event] instance of event
|
52
|
+
def create_event(event_class, appliance, transfer_method, parameters)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'nifty/backends/utils/opennebula'
|
3
|
+
require 'chronic_duration'
|
4
|
+
|
5
|
+
# OpenNebula backend
|
6
|
+
class Nifty::Backends::Opennebula < Nifty::Backend
|
7
|
+
class << self
|
8
|
+
# @see Nifty::Backend#backend?
|
9
|
+
def backend?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
# @see Nifty::Backend#description
|
14
|
+
def description
|
15
|
+
"OpenNebula backend"
|
16
|
+
end
|
17
|
+
|
18
|
+
# @see Nifty::Backend#options
|
19
|
+
def options
|
20
|
+
{ :secret => {
|
21
|
+
:type => :string,
|
22
|
+
:desc => 'Pair of username and password in form of \'username:password\' for accessing OpenNebula'
|
23
|
+
},
|
24
|
+
:endpoint => {
|
25
|
+
:type => :string,
|
26
|
+
:desc => 'OpenNebula\'s XML RPC endpoint'
|
27
|
+
},
|
28
|
+
:"expiration-interval" => {
|
29
|
+
:required => true,
|
30
|
+
:type => :string,
|
31
|
+
:desc => 'How long should expired images be kept in OpenNebula befor removal, 0 means don\'t remove'
|
32
|
+
},
|
33
|
+
:datastores => {
|
34
|
+
:required => true,
|
35
|
+
:type => :array,
|
36
|
+
:aliases => '-d',
|
37
|
+
:desc => 'Names of OpenNebula datastores images will be uploaded to'
|
38
|
+
},
|
39
|
+
:"template-dir" => {
|
40
|
+
:default => File.join(Nifty::GEM_DIR, 'config', 'templates'),
|
41
|
+
:type => :string,
|
42
|
+
:desc => 'If set, templates within this directory are used to construct images and templates in OpenNebula'
|
43
|
+
},
|
44
|
+
:"description-naming" => {
|
45
|
+
:type => :boolean,
|
46
|
+
:desc => 'If true, uses identifier and version from appliance description as template/image name instead of generated uuids'
|
47
|
+
},
|
48
|
+
:"disk-expiration" => {
|
49
|
+
:type => :boolean,
|
50
|
+
:desc => 'Will expire old disks before the new one is registered'
|
51
|
+
},
|
52
|
+
:permissions => {
|
53
|
+
:required => true,
|
54
|
+
:type => :string,
|
55
|
+
:desc => 'UNIX-like image and template permissions in OpenNebula'
|
56
|
+
}
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
# @see Nifty::Backend#pre
|
61
|
+
def pre(parameters)
|
62
|
+
expiration_check(parameters)
|
63
|
+
end
|
64
|
+
|
65
|
+
# @see Nifty::Backend#create_event
|
66
|
+
# @param [Hash] parameters
|
67
|
+
# @option parameters [String] secret OpenNebula's secret
|
68
|
+
# @option parameters [String] endpoint OpenNebula's endpoint
|
69
|
+
# @option parameters [Array] datastores array of datastore names
|
70
|
+
# @option parameters [String] template-dir path to dir with image and template templates
|
71
|
+
def create_event(event_class, appliance, transfer_method, parameters)
|
72
|
+
client = Nifty::Backends::Utils::Opennebula::Helper.client(parameters[:secret], parameters[:endpoint])
|
73
|
+
datastores = Nifty::Backends::Utils::Opennebula::DatastoreHandler.new(client).datastores(parameters[:datastores])
|
74
|
+
event_class.new(appliance, transfer_method, client, datastores, parameters)
|
75
|
+
rescue Nifty::Errors::Backends::OpennebulaError => ex
|
76
|
+
fail Nifty::Errors::BackendError, ex
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# Checks whether there are expired images that should be removed
|
82
|
+
#
|
83
|
+
# @param [Hash] parameters
|
84
|
+
# @option parameters [String] expiration-interval expiration interval in human readable form
|
85
|
+
# @option parameters [String] secret OpenNebula's secret
|
86
|
+
# @option parameters [String] endpoint OpenNebula's endpoint
|
87
|
+
def expiration_check(parameters)
|
88
|
+
interval = ChronicDuration.parse(parameters[:"expiration-interval"])
|
89
|
+
return unless interval
|
90
|
+
|
91
|
+
client = Nifty::Backends::Utils::Opennebula::Helper.client(parameters[:secret], parameters[:endpoint])
|
92
|
+
image_handler = Nifty::Backends::Utils::Opennebula::ImageHandler.new(client)
|
93
|
+
now = Time.now
|
94
|
+
|
95
|
+
logger.debug('Looking for expired images...')
|
96
|
+
image_handler.expired_images.each do |image|
|
97
|
+
image_handler.disable_image image
|
98
|
+
|
99
|
+
image_expiration_date = Time.parse(image['TEMPLATE/NIFTY_EXPIRATION'])
|
100
|
+
# checks whether image is already expired for specified time
|
101
|
+
next if (now - image_expiration_date) < interval
|
102
|
+
|
103
|
+
image_handler.delete_image image
|
104
|
+
end
|
105
|
+
rescue Nifty::Errors::Backends::OpennebulaError => ex
|
106
|
+
logger.error("Cannot check and remove expired images: #{ex.message}")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Handler for OpenNebula DatastorePool
|
2
|
+
#
|
3
|
+
# @author Michal Kimle
|
4
|
+
class Nifty::Backends::Utils::Opennebula::DatastoreHandler < Nifty::Backends::Utils::Opennebula::Handler
|
5
|
+
|
6
|
+
# Constructor
|
7
|
+
#
|
8
|
+
# @see Nifty::Backends::Utils::Opennebula::Handler#initialize
|
9
|
+
def initialize(client)
|
10
|
+
super(client)
|
11
|
+
@pool = OpenNebula::DatastorePool.new(client)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns list of datastores matching the names
|
15
|
+
# If there is no datastore with given name, it's skipped.
|
16
|
+
#
|
17
|
+
# @param [Array] names array of the names
|
18
|
+
# @return [Array] array of found datastores
|
19
|
+
def datastores(names)
|
20
|
+
reload!
|
21
|
+
|
22
|
+
datastores = []
|
23
|
+
names.each do |name|
|
24
|
+
datastore = pool.find { |ds| ds.name == name }
|
25
|
+
|
26
|
+
unless datastore
|
27
|
+
logger.warn("Datastore #{name.inspect} was not found, skipping.")
|
28
|
+
next
|
29
|
+
end
|
30
|
+
|
31
|
+
datastores << datastore
|
32
|
+
end
|
33
|
+
|
34
|
+
datastores
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Handler for OpenNebula GroupPool
|
2
|
+
#
|
3
|
+
# @author Michal Kimle
|
4
|
+
class Nifty::Backends::Utils::Opennebula::GroupHandler < Nifty::Backends::Utils::Opennebula::Handler
|
5
|
+
|
6
|
+
# Constructor
|
7
|
+
#
|
8
|
+
# @see Nifty::Backends::Utils::Opennebula::Handler#initialize
|
9
|
+
def initialize(client)
|
10
|
+
super(client)
|
11
|
+
@pool = OpenNebula::GroupPool.new(client)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns groupt with specified name
|
15
|
+
#
|
16
|
+
# @param [String] name
|
17
|
+
# @return [OpenNebula::Group] group with specified name
|
18
|
+
def group(name)
|
19
|
+
reload!
|
20
|
+
|
21
|
+
pool.find { |group| group.name == name }
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Handler for OpenNebula pools
|
2
|
+
#
|
3
|
+
# @author Michal Kimle
|
4
|
+
# @abstract
|
5
|
+
# @attr_reader [OpenNebula::Client] client
|
6
|
+
# @attr [OpenNebula::Pool] pool
|
7
|
+
class Nifty::Backends::Utils::Opennebula::Handler
|
8
|
+
attr_reader :client
|
9
|
+
attr_accessor :pool
|
10
|
+
|
11
|
+
ONEADMIN_ID = 0
|
12
|
+
LEAVE_AS_IS = -1
|
13
|
+
ATTRIBUTE_APPLIANCE_ID = 'NIFTY_APPLIANCE_ID'
|
14
|
+
OWNER_OCTET = '600'
|
15
|
+
|
16
|
+
# Constructor
|
17
|
+
#
|
18
|
+
# @param [OpenNebula::Client] client
|
19
|
+
def initialize(client)
|
20
|
+
@client = client
|
21
|
+
end
|
22
|
+
|
23
|
+
# Reloads the pool
|
24
|
+
#
|
25
|
+
def reload!
|
26
|
+
return unless pool
|
27
|
+
|
28
|
+
if pool.respond_to?('info_all!')
|
29
|
+
Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { pool.info_all! }
|
30
|
+
return
|
31
|
+
end
|
32
|
+
|
33
|
+
Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { pool.info! }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Change owner of the element
|
37
|
+
#
|
38
|
+
# @param [OpenNebula::PoolElement] element
|
39
|
+
# @param [Fixnum] owner_id
|
40
|
+
# @param [Fixnum] group_id
|
41
|
+
def self.chown(element, owner_id, group_id)
|
42
|
+
Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { element.info! }
|
43
|
+
|
44
|
+
old_owner_id = element['UID'].to_i
|
45
|
+
old_group_id = element.gid
|
46
|
+
owner_id = LEAVE_AS_IS if owner_id == old_owner_id
|
47
|
+
group_id = LEAVE_AS_IS if group_id == old_group_id
|
48
|
+
|
49
|
+
Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { element.chown(owner_id, group_id) }
|
50
|
+
end
|
51
|
+
|
52
|
+
# Change permissions on the element
|
53
|
+
#
|
54
|
+
# @param [OpenNebula::PoolElement] element
|
55
|
+
# @param [String] octet UNIX-like permission octet
|
56
|
+
def self.chmod(element, octet)
|
57
|
+
Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { element.info! }
|
58
|
+
Nifty::Backends::Utils::Opennebula::Helper.handle_opennebula_error { element.chmod_octet(octet) }
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'opennebula'
|
2
|
+
|
3
|
+
# Helper class for OpenNebula backend
|
4
|
+
#
|
5
|
+
# @author Michal Kimle
|
6
|
+
class Nifty::Backends::Utils::Opennebula::Helper
|
7
|
+
class << self
|
8
|
+
# Creates client for communication with OpenNebula
|
9
|
+
#
|
10
|
+
# @param [String] secret OpenNebula's authentication secret
|
11
|
+
# @param [String] endpoint OpenNebula's endpoint
|
12
|
+
# @return [OpenNebula::Client] OpenNebula client instance
|
13
|
+
def client(secret, endpoint)
|
14
|
+
OpenNebula::Client.new(secret, endpoint)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Handles OpenNebula error codes and turn them into exceptions
|
18
|
+
#
|
19
|
+
# @raise [Nifty::Errors::Backends::Opennebula::AuthenticationError]
|
20
|
+
# @raise [Nifty::Errors::Backends::Opennebula::UserNotAuthorizedError]
|
21
|
+
# @raise [Nifty::Errors::Backends::Opennebula::ResourceNotFoundError]
|
22
|
+
# @raise [Nifty::Errors::Backends::Opennebula::ResourceStateError]
|
23
|
+
# @raise [Nifty::Errors::Backends::Opennebula::ResourceRetrievalError]
|
24
|
+
def handle_opennebula_error
|
25
|
+
fail Nifty::Errors::Backends::Opennebula::StubError, 'OpenNebula service-wrapper was called without a block!' unless block_given?
|
26
|
+
|
27
|
+
return_value = yield
|
28
|
+
return return_value unless OpenNebula.is_error?(return_value)
|
29
|
+
|
30
|
+
case return_value.errno
|
31
|
+
when OpenNebula::Error::EAUTHENTICATION
|
32
|
+
fail Nifty::Errors::Backends::Opennebula::AuthenticationError, return_value.message
|
33
|
+
when OpenNebula::Error::EAUTHORIZATION
|
34
|
+
fail Nifty::Errors::Backends::Opennebula::UserNotAuthorizedError, return_value.message
|
35
|
+
when OpenNebula::Error::ENO_EXISTS
|
36
|
+
fail Nifty::Errors::Backends::Opennebula::ResourceNotFoundError, return_value.message
|
37
|
+
when OpenNebula::Error::EACTION
|
38
|
+
fail Nifty::Errors::Backends::Opennebula::ResourceStateError, return_value.message
|
39
|
+
else
|
40
|
+
fail Nifty::Errors::Backends::Opennebula::ResourceRetrievalError, return_value.message
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|