itchy 0.2.7 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +119 -2
- data/bin/itchy +14 -15
- data/itchy.gemspec +1 -0
- data/lib/itchy.rb +7 -0
- data/lib/itchy/image_transformer.rb +104 -12
- data/lib/itchy/version.rb +1 -1
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10b5ecfa7e3bc071fecc195d65a0169f0b7545ea
|
4
|
+
data.tar.gz: 29c643ccf9dce7e83730e68edefb64ab8e70768d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8359f10ef113911af9947c0eaafc580da3c7040b081d2198eb83783f09a0d129d52e5ed595128c0555bea5a40447b7f7485381edde921d96181a6da4c817e629
|
7
|
+
data.tar.gz: ab5fb5cf07d9c7f8e38a0c82300e391eda804bb6e9a948baef2e35376ad37d1c4f11269cc7a6ea4b637837a1d0fe6b4431bfd3b7f7f5396599a243e013aa5119
|
data/README.md
CHANGED
@@ -3,10 +3,127 @@
|
|
3
3
|
[![Gem Version](https://fury-badge.herokuapp.com/rb/onevmcatcher.png)](https://badge.fury.io/rb/itchy)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/arax/onevmcatcher.png)](https://codeclimate.com/github/kosoburak/itchy)
|
5
5
|
|
6
|
-
# Itchy
|
6
|
+
# Itchy - vIrTual applianCe Handling utiliTY
|
7
7
|
|
8
|
-
|
8
|
+
ITCHY is tool for handling virtual appliances.
|
9
9
|
|
10
|
+
## Related tools
|
11
|
+
ITCHY is part of tool chain used for automated virtual applience handling.
|
12
|
+
Because of character of this tool, separated usage is not really helpfull.
|
13
|
+
|
14
|
+
Part of ITCHY is designed to be an event handler for [vmcatcher](https://github.com/hepix-virtualisation/vmcatcher).
|
15
|
+
|
16
|
+
Files created by ITCHY are intended to be uploated and registered in a cloud storage.
|
17
|
+
This can be done by our other tool [nifty](https://github.com/CESNET/nifty).
|
18
|
+
|
19
|
+
## What and how does ITCHY do?
|
20
|
+
|
21
|
+
It basically converts heterogeneous output from vmcatcher and prepare all necessary files for upload an registration into a cloud storage.
|
22
|
+
|
23
|
+
ITCHY consists of two cooperating tasks. One serves for archiving vmcatcher events, second one for further processing. This concept was needed because of two reasons. First reason is that vmcatcher run as a cron job, regularly. There is a possibility, that image processing time would be greater than time period between two vmcatcher runs. In this case, the whole process would fail. The second reason is that we can't interrupt vmcatcher event processing and start over. So, the first part of ITCHY running with vmcatcher as event handler is so simple as it can be. The other acts are separated and they can be restarted or delayed if there is a need to do so, and it won't affect vmcatcher.
|
24
|
+
|
25
|
+
## Instalation
|
26
|
+
|
27
|
+
###From distribution specific packages
|
28
|
+
Distribution specific packages can be created with [omnibus packaging for ITCHY](https://github.com/CESNET/omnibus-itchy). When installing via packages you don't have to install neither ruby nor rubygems. Packages contain embedded ruby and all the necessary gems and libraries witch will not effect your system ruby, gems and libraries.
|
29
|
+
|
30
|
+
Currently supported distributions:
|
31
|
+
|
32
|
+
Ubuntu 12.04
|
33
|
+
Ubuntu 14.04
|
34
|
+
Debian 7.6
|
35
|
+
Debian 8.2
|
36
|
+
CentOS 6.5
|
37
|
+
CentOS 7.1
|
38
|
+
|
39
|
+
###From RubyGems.org
|
40
|
+
To install the most recent stable version
|
41
|
+
``bash
|
42
|
+
gem install nifty
|
43
|
+
``
|
44
|
+
|
45
|
+
###From source (dev)
|
46
|
+
**Installation from source should never be your first choice! Especially, if you are not
|
47
|
+
familiar with RVM, Bundler, Rake and other dev tools for Ruby!**
|
48
|
+
|
49
|
+
**However, if you wish to contribute to our project, this is the right way to start.**
|
50
|
+
|
51
|
+
To build and install the bleeding edge version from master
|
52
|
+
|
53
|
+
```bash
|
54
|
+
git clone git://github.com/CESNET/itchy.git
|
55
|
+
cd itchy
|
56
|
+
gem install bundler
|
57
|
+
bundle install
|
58
|
+
bundle exec rake spec
|
59
|
+
```
|
60
|
+
|
61
|
+
## Configuration
|
62
|
+
###Create a configuration file for ITCHY
|
63
|
+
Configuration file can be read by ITCHY from these
|
64
|
+
three locations:
|
65
|
+
|
66
|
+
* `~/.itchy/itchy.yml`
|
67
|
+
* `/etc/itchy/itchy.yml`
|
68
|
+
* `PATH_TO_GEM_DIR/config/itchy.yml`
|
69
|
+
|
70
|
+
The default configuration file can be found at the last location
|
71
|
+
`PATH_TO_GEM_DIR/config/itchy.yml`.
|
72
|
+
|
73
|
+
## Usage
|
74
|
+
ITCHY starts with executable `itchy`. For further assistance run `itchy help`:
|
75
|
+
```bash
|
76
|
+
$ itchy help
|
77
|
+
|
78
|
+
Commands:
|
79
|
+
itchy archive # Handle an incoming vmcatcher event and store it for further processing
|
80
|
+
itchy help [COMMAND] # Describe available commands or one specific command
|
81
|
+
itchy process # Process stored events
|
82
|
+
|
83
|
+
Options:
|
84
|
+
-b, [--log-level=LOG_LEVEL] # Logging level
|
85
|
+
# Default: error
|
86
|
+
# Possible values: debug, info, warn, error, fatal, unknown
|
87
|
+
-d, [--debug], [--no-debug] # Enable debugging
|
88
|
+
```
|
89
|
+
### ARCHIVE
|
90
|
+
This command is used as an event handler for `vmcatcher`.
|
91
|
+
For proper running it needs to have set required env variables by `vmcatcher`.
|
92
|
+
```bash
|
93
|
+
$ itchy help archive
|
94
|
+
|
95
|
+
```
|
96
|
+
### PROCESS
|
97
|
+
|
98
|
+
```bash
|
99
|
+
$itchy help process
|
100
|
+
|
101
|
+
Usage:
|
102
|
+
itchy process
|
103
|
+
|
104
|
+
Options:
|
105
|
+
-m, [--metadata-dir=METADATA_DIR] # Path to a metadata directory for stored events
|
106
|
+
# Default: /var/spool/itchy/metadata
|
107
|
+
-f, [--required-format=REQUIRED_FORMAT] # Required output format of converted images
|
108
|
+
# Default: qcow2
|
109
|
+
-o, [--output-dir=OUTPUT_DIR] # Path to a directory where processed events descriptors will be stored
|
110
|
+
# Default: /var/spool/itchy/output
|
111
|
+
-t, [--temp-image-dir=TEMP_IMAGE_DIR] # Path to a directory where images will be temporary stored while being processed
|
112
|
+
# Default: /var/spool/itchy/temp
|
113
|
+
-e, [--descriptor-dir=DESCRIPTOR_DIR] # Path to a directory where appliance descriptors will be stored
|
114
|
+
# Default: /var/spool/itchy/descriptors
|
115
|
+
-p, [--file-permissions=FILE_PERMISSIONS] # Sets permissions for all created files
|
116
|
+
# Default: 0664
|
117
|
+
-l, [--log-to=LOG_TO] # Logging output, file path or stderr/stdout
|
118
|
+
# Default: /var/log/itchy/process.log
|
119
|
+
-q, [--qemu-img-binary=QEMU_IMG_BINARY] # Path to qemu-img command binary, if not used, ITCHY will look for it in PATH
|
120
|
+
-b, [--log-level=LOG_LEVEL] # Logging level
|
121
|
+
# Default: error
|
122
|
+
# Possible values: debug, info, warn, error, fatal, unknown
|
123
|
+
-d, [--debug], [--no-debug] # Enable debugging
|
124
|
+
|
125
|
+
Process stored events
|
126
|
+
```
|
10
127
|
## Contributing
|
11
128
|
|
12
129
|
1. Fork it ( https://github.com/kosoburak/itchy/fork )
|
data/bin/itchy
CHANGED
@@ -33,12 +33,17 @@ class ItchyRunnable < Thor
|
|
33
33
|
AVAILABLE_AUTH_METHODS = %w(none basic).freeze
|
34
34
|
ERROR_EXIT_CODE = 1
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
class_option :log_level,
|
37
|
+
enum: AVAILABLE_LOG_LEVELS,
|
38
|
+
default: Itchy::Settings.log_level,
|
39
|
+
aliases: '-b',
|
40
|
+
desc: 'Logging level'
|
41
|
+
|
42
|
+
class_option :debug,
|
43
|
+
type: :boolean,
|
44
|
+
default: Itchy::Settings.debug,
|
45
|
+
aliases: '-d',
|
46
|
+
desc: 'Enable debugging'
|
42
47
|
|
43
48
|
# Static method required by Thor to make certain
|
44
49
|
# actions work.
|
@@ -57,8 +62,8 @@ class ItchyRunnable < Thor
|
|
57
62
|
method_option :log_to,
|
58
63
|
type: :string,
|
59
64
|
default: Itchy::Settings.log_to.archive_log,
|
60
|
-
|
61
|
-
desc: 'Logging output, file path or stderr/stdout'
|
65
|
+
aliases: '-l',
|
66
|
+
desc: 'Logging output for archive command, file path or stderr/stdout'
|
62
67
|
|
63
68
|
method_option :file_permissions,
|
64
69
|
type: :string,
|
@@ -66,9 +71,6 @@ class ItchyRunnable < Thor
|
|
66
71
|
aliases: '-p',
|
67
72
|
desc: 'Sets permissions for all created files'
|
68
73
|
|
69
|
-
method_option *shared_option_log_level
|
70
|
-
method_option *shared_option_debug
|
71
|
-
|
72
74
|
def archive
|
73
75
|
check_restrictions
|
74
76
|
opts = normalize_options
|
@@ -125,7 +127,7 @@ class ItchyRunnable < Thor
|
|
125
127
|
type: :string,
|
126
128
|
default: Itchy::Settings.log_to.process_log,
|
127
129
|
aliases: '-l',
|
128
|
-
desc: 'Logging output, file path or stderr/stdout'
|
130
|
+
desc: 'Logging output for process command, file path or stderr/stdout'
|
129
131
|
|
130
132
|
|
131
133
|
method_option :qemu_img_binary,
|
@@ -134,9 +136,6 @@ class ItchyRunnable < Thor
|
|
134
136
|
aliases: '-q',
|
135
137
|
desc: 'Path to qemu-img command binary, if not used, ITCHY will look for it in PATH'
|
136
138
|
|
137
|
-
method_option *shared_option_log_level
|
138
|
-
method_option *shared_option_debug
|
139
|
-
|
140
139
|
def process
|
141
140
|
check_restrictions
|
142
141
|
opts = normalize_options
|
data/itchy.gemspec
CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |gem|
|
|
29
29
|
gem.add_dependency 'hashie', '~> 3.3', '>= 3.3.1'
|
30
30
|
gem.add_dependency 'thor', '~> 0.19', '>= 0.19.1'
|
31
31
|
gem.add_dependency 'cloud-appliance-descriptor', '~> 0.2'
|
32
|
+
gem.add_dependency 'nokogiri', '~>1.6', '>= 1.6.7'
|
32
33
|
|
33
34
|
gem.add_development_dependency 'bundler', '~> 1.6'
|
34
35
|
gem.add_development_dependency 'rake', '~> 10.0'
|
data/lib/itchy.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'active_support/all'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'nokogiri'
|
2
4
|
require 'settingslogic'
|
3
5
|
require 'multi_json'
|
4
6
|
require 'mixlib/shellout'
|
@@ -7,12 +9,17 @@ require 'uri'
|
|
7
9
|
require 'erb'
|
8
10
|
require 'hashie/mash'
|
9
11
|
require 'cloud-appliance-descriptor'
|
12
|
+
require 'rubygems/package'
|
10
13
|
|
11
14
|
# Wraps all internals of the handler.
|
12
15
|
module Itchy
|
13
16
|
BASIC_QEMU_COMMAND = 'qemu-img'
|
17
|
+
GEM_DIR = File.realdirpath(File.join(File.dirname(__FILE__), '..'))
|
18
|
+
XSD_SCHEMA = File.join(GEM_DIR, 'resources', 'dsp8023_2.0.1.xsd')
|
19
|
+
XSD_DIR = File.join(GEM_DIR, 'resources')
|
14
20
|
end
|
15
21
|
|
22
|
+
|
16
23
|
require 'itchy/version'
|
17
24
|
require 'itchy/settings'
|
18
25
|
require 'itchy/log'
|
@@ -8,6 +8,9 @@ module Itchy
|
|
8
8
|
# Archive format string msg
|
9
9
|
ARCHIVE_STRING = 'POSIX tar archive'
|
10
10
|
|
11
|
+
# raw boot sector message
|
12
|
+
REAL_RAW_STRING = 'boot sector'
|
13
|
+
|
11
14
|
# REGEX pattern for getting image format
|
12
15
|
FORMAT_PATTERN = /format:\s(.*?)$/
|
13
16
|
|
@@ -34,12 +37,20 @@ module Itchy
|
|
34
37
|
def transform!(metadata, vmcatcher_configuration)
|
35
38
|
Itchy::Log.info "[#{self.class.name}] Transforming image format " \
|
36
39
|
"for #{metadata.dc_identifier.inspect}"
|
40
|
+
|
41
|
+
image_file = orig_image_file(metadata, vmcatcher_configuration)
|
42
|
+
|
43
|
+
unless File.file?(image_file)
|
44
|
+
Itchy::Log.error "[#{self.class.name}] Event image file - #{image_file}] - does not exist!"
|
45
|
+
fail Itchy::Errors::ImageTransformationError
|
46
|
+
end
|
47
|
+
|
37
48
|
begin
|
38
|
-
if archived?(
|
39
|
-
unpacking_dir =
|
40
|
-
file_format =
|
49
|
+
if archived?(image_file)
|
50
|
+
unpacking_dir = process_archive(metadata, vmcatcher_configuration)
|
51
|
+
file_format = format("#{unpacking_dir}/#{metadata.dc_identifier}")
|
41
52
|
else
|
42
|
-
file_format = format(
|
53
|
+
file_format = format(image_file)
|
43
54
|
unpacking_dir = copy_unpacked!(metadata, vmcatcher_configuration)
|
44
55
|
end
|
45
56
|
if file_format == @options.required_format
|
@@ -82,9 +93,85 @@ module Itchy
|
|
82
93
|
Itchy::Log.error "Image format #{file_format} is unknown and not supported!"
|
83
94
|
fail Itchy::Errors::FileInspectError
|
84
95
|
end
|
96
|
+
if file_format.eql? "raw" then
|
97
|
+
unless check_real_raw(file)
|
98
|
+
Itchy::Log.error "Image format is not a real RAW, it has no boot sector!"
|
99
|
+
fail Itchy::Errors::FileInspectError
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
85
103
|
file_format
|
86
104
|
end
|
87
105
|
|
106
|
+
def check_real_raw(file)
|
107
|
+
file_command(file).include? REAL_RAW_STRING
|
108
|
+
end
|
109
|
+
|
110
|
+
def process_archive(metadata, vmcatcher_configuration)
|
111
|
+
unpacking_dir = prepare_image_temp_dir(metadata, vmcatcher_configuration)
|
112
|
+
File.open(orig_image_file(metadata, vmcatcher_configuration), "rb") do |file|
|
113
|
+
Gem::Package::TarReader.new(file) do |archive|
|
114
|
+
disk_name = nil
|
115
|
+
archive.each do |entry|
|
116
|
+
Itchy::Log.debug "EACH NAME: #{entry.full_name}"
|
117
|
+
if File.extname(entry.full_name).eql? ".ovf" then
|
118
|
+
File.open("#{unpacking_dir}/#{entry.full_name}", "wb") do |f|
|
119
|
+
f.write(entry.read)
|
120
|
+
end
|
121
|
+
disk_name = process_ovf("#{unpacking_dir}/#{entry.full_name}")
|
122
|
+
Itchy::Log.debug "FOUND DISK NAME FROM OVF: #{disk_name}"
|
123
|
+
break
|
124
|
+
end
|
125
|
+
end
|
126
|
+
begin
|
127
|
+
archive.rewind()
|
128
|
+
archive.seek(disk_name) do |disk|
|
129
|
+
Itchy::Log.debug "Seeked disk - with name: #{disk.full_name}"
|
130
|
+
File.open("#{unpacking_dir}/#{metadata.dc_identifier}", "wb") do |f|
|
131
|
+
until disk.eof?
|
132
|
+
output = disk.read(50000000)
|
133
|
+
f.write(output)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
rescue => e
|
138
|
+
Ichy::Log.error e.message
|
139
|
+
Itchy::Log.error e.backtrace.join("\n")
|
140
|
+
fail e
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
unpacking_dir
|
146
|
+
end
|
147
|
+
|
148
|
+
def process_ovf(ovf_file)
|
149
|
+
Itchy::Log.debug "PROCESSING OVF FILE: #{ovf_file}"
|
150
|
+
doc = Nokogiri::XML(File.open(ovf_file))
|
151
|
+
#validate_ovf(doc)
|
152
|
+
if doc.css("Envelope DiskSection Disk").count != 1
|
153
|
+
Itchy::Log.error "[#{self.class.name}] Unsupported ova, contains 0 or more than one disk!"
|
154
|
+
fail Itchy::Errors::FileInspectError
|
155
|
+
end
|
156
|
+
# return the name of disk
|
157
|
+
doc.css("Envelope References File").attr("href").value
|
158
|
+
end
|
159
|
+
|
160
|
+
# Validation is not used for now
|
161
|
+
def validate_ovf(doc)
|
162
|
+
Itchy::Log.debug "VALIDATING from DIR: #{XSD_DIR} with schema #{XSD_SCHEMA}"
|
163
|
+
Dir.chdir(XSD_DIR) do
|
164
|
+
xsd = Nokogiri::XML::Schema(File.read(XSD_SCHEMA))
|
165
|
+
xsd.validate(doc).each do |error|
|
166
|
+
Itchy::Log.error "VALIDATION ERROR: #{error.message}"
|
167
|
+
end
|
168
|
+
unless xsd.valid?(doc) then
|
169
|
+
Itchy::Log.error "[#{self.class.name}] OVF validation failed!"
|
170
|
+
fail Itchy::Errors::FileInspectError
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
88
175
|
#
|
89
176
|
#
|
90
177
|
# @param metadata [Itchy::VmcatcherEvent] event metadata
|
@@ -215,14 +302,11 @@ module Itchy
|
|
215
302
|
"#{ex.message}"
|
216
303
|
fail Itchy::Errors::PrepareEnvError, ex
|
217
304
|
end
|
305
|
+
temp_dir
|
218
306
|
end
|
219
307
|
|
220
|
-
|
221
|
-
|
222
|
-
# @param file [String] inspected file name
|
223
|
-
# @return [Boolean] archived or not
|
224
|
-
def archived?(file)
|
225
|
-
image_format_tester = Mixlib::ShellOut.new("file #{file}")
|
308
|
+
def file_command(file)
|
309
|
+
image_format_tester = Mixlib::ShellOut.new("file --brief #{file}")
|
226
310
|
image_format_tester.run_command
|
227
311
|
begin
|
228
312
|
image_format_tester.error!
|
@@ -231,9 +315,17 @@ module Itchy
|
|
231
315
|
Itchy::Log.error "[#{self.class.name}] Checking file format for" \
|
232
316
|
"#{file} failed with #{image_format_tester.stderr}"
|
233
317
|
fail Itchy::Errors::FileInspectError, ex
|
234
|
-
|
235
318
|
end
|
236
|
-
|
319
|
+
image_format_tester.stdout
|
320
|
+
end
|
321
|
+
|
322
|
+
|
323
|
+
# Checks if file is archived image (format ova or tar)
|
324
|
+
#
|
325
|
+
# @param file [String] inspected file name
|
326
|
+
# @return [Boolean] archived or not
|
327
|
+
def archived?(file)
|
328
|
+
temp = file_command(file)
|
237
329
|
temp.include? ARCHIVE_STRING
|
238
330
|
end
|
239
331
|
end
|
data/lib/itchy/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: itchy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lubomir Kosaristan
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-05-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: opennebula
|
@@ -205,6 +205,26 @@ dependencies:
|
|
205
205
|
- - "~>"
|
206
206
|
- !ruby/object:Gem::Version
|
207
207
|
version: '0.2'
|
208
|
+
- !ruby/object:Gem::Dependency
|
209
|
+
name: nokogiri
|
210
|
+
requirement: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - "~>"
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '1.6'
|
215
|
+
- - ">="
|
216
|
+
- !ruby/object:Gem::Version
|
217
|
+
version: 1.6.7
|
218
|
+
type: :runtime
|
219
|
+
prerelease: false
|
220
|
+
version_requirements: !ruby/object:Gem::Requirement
|
221
|
+
requirements:
|
222
|
+
- - "~>"
|
223
|
+
- !ruby/object:Gem::Version
|
224
|
+
version: '1.6'
|
225
|
+
- - ">="
|
226
|
+
- !ruby/object:Gem::Version
|
227
|
+
version: 1.6.7
|
208
228
|
- !ruby/object:Gem::Dependency
|
209
229
|
name: bundler
|
210
230
|
requirement: !ruby/object:Gem::Requirement
|