vagrant-abiquo 0.0.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 +7 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +106 -0
- data/LICENSE.txt +22 -0
- data/README.md +106 -0
- data/Rakefile +22 -0
- data/Vagrantfile +21 -0
- data/box/abiquo.box +0 -0
- data/box/metadata.json +3 -0
- data/lib/vagrant-abiquo.rb +14 -0
- data/lib/vagrant-abiquo/actions.rb +86 -0
- data/lib/vagrant-abiquo/actions/check_state.rb +19 -0
- data/lib/vagrant-abiquo/actions/create.rb +113 -0
- data/lib/vagrant-abiquo/actions/destroy.rb +35 -0
- data/lib/vagrant-abiquo/actions/modify_provision_path.rb +38 -0
- data/lib/vagrant-abiquo/actions/power_off.rb +33 -0
- data/lib/vagrant-abiquo/actions/power_on.rb +34 -0
- data/lib/vagrant-abiquo/actions/reload.rb +31 -0
- data/lib/vagrant-abiquo/config.rb +49 -0
- data/lib/vagrant-abiquo/errors.rb +33 -0
- data/lib/vagrant-abiquo/helpers/client.rb +149 -0
- data/lib/vagrant-abiquo/helpers/result.rb +40 -0
- data/lib/vagrant-abiquo/plugin.rb +22 -0
- data/lib/vagrant-abiquo/provider.rb +121 -0
- data/lib/vagrant-abiquo/version.rb +5 -0
- data/locales/en.yml +103 -0
- data/test/Vagrantfile +22 -0
- data/test/scripts/provision.sh +3 -0
- data/test/test.sh +11 -0
- data/vagrant-abiquo.gemspec +21 -0
- metadata +118 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'vagrant-abiquo/helpers/client'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Abiquo
|
5
|
+
module Actions
|
6
|
+
class Destroy
|
7
|
+
include Helpers::Client
|
8
|
+
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@machine = env[:machine]
|
12
|
+
@client = client
|
13
|
+
@logger = Log4r::Logger.new('vagrant::abiquo::destroy')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# submit destroy droplet request
|
18
|
+
# result = @client.request("/droplets/#{@machine.id}/destroy")
|
19
|
+
|
20
|
+
env[:ui].info I18n.t('vagrant_abiquo.info.destroying')
|
21
|
+
|
22
|
+
# wait for the destroy progress to start
|
23
|
+
# @client.wait_for_event(env, result['event_id']) do |response|
|
24
|
+
# break if response['event']['percentage'] != nil
|
25
|
+
# end
|
26
|
+
|
27
|
+
# set the machine id to nil to cleanup local vagrant state
|
28
|
+
@machine.id = nil
|
29
|
+
|
30
|
+
@app.call(env)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module DigitalOcean
|
3
|
+
module Actions
|
4
|
+
class ModifyProvisionPath
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
@machine = env[:machine]
|
8
|
+
@logger =
|
9
|
+
Log4r::Logger.new('vagrant::digitalocean::modify_provision_path')
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
# check if provisioning is enabled
|
14
|
+
enabled = true
|
15
|
+
enabled = env[:provision_enabled] if env.has_key?(:provision_enabled)
|
16
|
+
return @app.call(env) if !enabled
|
17
|
+
|
18
|
+
username = @machine.ssh_info()[:username]
|
19
|
+
|
20
|
+
# change ownership of the provisioning path recursively to the
|
21
|
+
# ssh user
|
22
|
+
#
|
23
|
+
# TODO submit patch to vagrant to set appropriate permissions
|
24
|
+
# based on ssh username
|
25
|
+
@machine.config.vm.provisioners.each do |provisioner|
|
26
|
+
cfg = provisioner.config
|
27
|
+
path = cfg.upload_path if cfg.respond_to? :upload_path
|
28
|
+
path = cfg.provisioning_path if cfg.respond_to? :provisioning_path
|
29
|
+
@machine.communicate.sudo("chown -R #{username} #{path}",
|
30
|
+
:error_check => false)
|
31
|
+
end
|
32
|
+
|
33
|
+
@app.call(env)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'vagrant-abiquo/helpers/client'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Abiquo
|
5
|
+
module Actions
|
6
|
+
class PowerOff
|
7
|
+
include Helpers::Client
|
8
|
+
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@machine = env[:machine]
|
12
|
+
@client = client
|
13
|
+
@logger = Log4r::Logger.new('vagrant::abiquo::power_off')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# submit power off droplet request
|
18
|
+
# result = @client.request("/droplets/#{@machine.id}/power_off")
|
19
|
+
|
20
|
+
# wait for request to complete
|
21
|
+
# env[:ui].info I18n.t('vagrant_abiquo.info.powering_off')
|
22
|
+
# @client.wait_for_event(env, result['event_id'])
|
23
|
+
|
24
|
+
# refresh droplet state with provider
|
25
|
+
# Provider.droplet(@machine, :refresh => true)
|
26
|
+
|
27
|
+
@app.call(env)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'vagrant-abiquo/helpers/client'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Abiquo
|
5
|
+
module Actions
|
6
|
+
class PowerOn
|
7
|
+
include Helpers::Client
|
8
|
+
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@machine = env[:machine]
|
12
|
+
@client = client
|
13
|
+
@logger = Log4r::Logger.new('vagrant::abiquo::power_on')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# submit power on droplet request
|
18
|
+
# result = @client.request("/droplets/#{@machine.id}/power_on")
|
19
|
+
|
20
|
+
# wait for request to complete
|
21
|
+
# env[:ui].info I18n.t('vagrant_abiquo.info.powering_on')
|
22
|
+
# @client.wait_for_event(env, result['event_id'])
|
23
|
+
|
24
|
+
# refresh droplet state with provider
|
25
|
+
# Provider.droplet(@machine, :refresh => true)
|
26
|
+
|
27
|
+
@app.call(env)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'vagrant-digitalocean/helpers/client'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module DigitalOcean
|
5
|
+
module Actions
|
6
|
+
class Reload
|
7
|
+
include Helpers::Client
|
8
|
+
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@machine = env[:machine]
|
12
|
+
@client = client
|
13
|
+
@logger = Log4r::Logger.new('vagrant::digitalocean::reload')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# submit reboot droplet request
|
18
|
+
result = @client.request("/droplets/#{@machine.id}/reboot")
|
19
|
+
|
20
|
+
# wait for request to complete
|
21
|
+
env[:ui].info I18n.t('vagrant_digital_ocean.info.reloading')
|
22
|
+
@client.wait_for_event(env, result['event_id'])
|
23
|
+
|
24
|
+
@app.call(env)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Abiquo
|
3
|
+
class Config < Vagrant.plugin('2', :config)
|
4
|
+
attr_accessor :abiquo_api_user
|
5
|
+
attr_accessor :abiquo_api_password
|
6
|
+
attr_accessor :abiquo_api_uri
|
7
|
+
attr_accessor :virtualdatacenter
|
8
|
+
attr_accessor :virtualappliance
|
9
|
+
attr_accessor :label
|
10
|
+
attr_accessor :exposed_nic
|
11
|
+
attr_accessor :template
|
12
|
+
attr_accessor :setup
|
13
|
+
|
14
|
+
alias_method :setup?, :setup
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@abiquo_api_user = UNSET_VALUE
|
18
|
+
@abiquo_api_password = UNSET_VALUE
|
19
|
+
@virtualdatacenter = UNSET_VALUE
|
20
|
+
@virtualappliance = UNSET_VALUE
|
21
|
+
@label = UNSET_VALUE
|
22
|
+
@template = UNSET_VALUE
|
23
|
+
@setup = UNSET_VALUE
|
24
|
+
end
|
25
|
+
|
26
|
+
def finalize!
|
27
|
+
@abiquo_api_user = ENV['ABIQUO_API_USER'] if @abiquo_api_user == UNSET_VALUE
|
28
|
+
@abiquo_api_password = ENV['ABIQUO_API_PASSWORD'] if @abiquo_api_password == UNSET_VALUE
|
29
|
+
@abiquo_api_uri = ENV['ABIQUO_API_URI'] if @abiquo_api_uri == UNSET_VALUE
|
30
|
+
@virtualdatacenter = 'VagrantVDC' if @virtualdatacenter == UNSET_VALUE
|
31
|
+
@virtualappliance = 'VagrantVAPP' if @virtualappliance == UNSET_VALUE
|
32
|
+
@label = 'VagrantVM' if @label == UNSET_VALUE
|
33
|
+
@template = 'TemplateImage' if @template == UNSET_VALUE
|
34
|
+
@setup = true if @setup == UNSET_VALUE
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate(machine)
|
38
|
+
errors = []
|
39
|
+
errors << I18n.t('vagrant_abiquo.config.abiquo_api_user') if !@abiquo_api_user
|
40
|
+
errors << I18n.t('vagrant_abiquo.config.abiquo_api_password') if !@abiquo_api_password
|
41
|
+
errors << I18n.t('vagrant_abiquo.config.abiquo_api_uri') if !@abiquo_api_uri
|
42
|
+
errors << I18n.t('vagrant_abiquo.config.virtualdatacenter') if !@virtualdatacenter
|
43
|
+
errors << I18n.t('vagrant_abiquo.config.template') if !@template
|
44
|
+
|
45
|
+
{ 'Abiquo Provider' => errors }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Abiquo
|
3
|
+
module Errors
|
4
|
+
class AbiquoError < Vagrant::Errors::VagrantError
|
5
|
+
error_namespace("vagrant_abiquo.errors")
|
6
|
+
end
|
7
|
+
|
8
|
+
class APIStatusError < AbiquoError
|
9
|
+
error_key(:api_status)
|
10
|
+
end
|
11
|
+
|
12
|
+
class APIFindError < AbiquoError
|
13
|
+
error_key(:apifind_error)
|
14
|
+
end
|
15
|
+
|
16
|
+
class RestClientError < AbiquoError
|
17
|
+
error_key(:restclient_error)
|
18
|
+
end
|
19
|
+
|
20
|
+
class JSONError < AbiquoError
|
21
|
+
error_key(:json)
|
22
|
+
end
|
23
|
+
|
24
|
+
class ResultMatchError < AbiquoError
|
25
|
+
error_key(:result_match)
|
26
|
+
end
|
27
|
+
|
28
|
+
class LocalIPError < AbiquoError
|
29
|
+
error_key(:local_ip)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'vagrant-abiquo/helpers/result'
|
2
|
+
require 'rest-client'
|
3
|
+
require 'json'
|
4
|
+
require 'log4r'
|
5
|
+
include Log4r
|
6
|
+
|
7
|
+
module VagrantPlugins
|
8
|
+
module Abiquo
|
9
|
+
module Helpers
|
10
|
+
module Client
|
11
|
+
def client
|
12
|
+
@client ||= ApiClient.new(@machine)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class ApiClient
|
17
|
+
include Vagrant::Util::Retryable
|
18
|
+
|
19
|
+
def initialize(machine)
|
20
|
+
@timeout = 60
|
21
|
+
@otimeout = 30
|
22
|
+
@logger = Log4r::Logger.new('vagrant::abiquo::apiclient')
|
23
|
+
@config = machine.provider_config
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_id(entity,entity_collection,name)
|
27
|
+
JSON.parse(entity_collection)['collection'].each do |collection|
|
28
|
+
if collection['name'] == name
|
29
|
+
return collection['id'].to_s
|
30
|
+
end
|
31
|
+
end
|
32
|
+
raise(Errors::APIFindError, {
|
33
|
+
:entity => entity,
|
34
|
+
:name => name
|
35
|
+
})
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_template(entity,entity_collection,name)
|
39
|
+
JSON.parse(entity_collection)['collection'].each do |collection|
|
40
|
+
if collection['name'] == name
|
41
|
+
collection['links'].each do |template_link|
|
42
|
+
if template_link['rel'] == "edit"
|
43
|
+
return template_link['href']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
raise(Errors::APIFindError, {
|
49
|
+
:entity => entity,
|
50
|
+
:name => name
|
51
|
+
})
|
52
|
+
end
|
53
|
+
|
54
|
+
# TO-DO
|
55
|
+
# Crear metodos de FIND_VDC / FIND_VAPP / FIND_VM y eliminarlos de create y provider
|
56
|
+
#
|
57
|
+
def http_request(resource, method, headers={}, data={})
|
58
|
+
begin
|
59
|
+
req = RestClient::Resource.new( resource, :user => @config.abiquo_api_user, :password => @config.abiquo_api_password, :timeout => @timeout, :open_timeout => @otimeout )
|
60
|
+
case method
|
61
|
+
when "GET"
|
62
|
+
if headers.nil? then
|
63
|
+
res = req.get
|
64
|
+
else
|
65
|
+
res = req.get(headers)
|
66
|
+
end
|
67
|
+
when "POST"
|
68
|
+
if headers.nil? then
|
69
|
+
res = req.post
|
70
|
+
else
|
71
|
+
res = req.post(data,headers)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
rescue => e
|
75
|
+
raise(Errors::RestClientError, {
|
76
|
+
:path => resource,
|
77
|
+
:headers => headers,
|
78
|
+
:data => data,
|
79
|
+
:response => e.to_s
|
80
|
+
})
|
81
|
+
end
|
82
|
+
if res.code == 202 or
|
83
|
+
res.code == 201 or
|
84
|
+
res.code == 200 then
|
85
|
+
return res.body
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# def request(path, params = {})
|
90
|
+
# begin
|
91
|
+
# @logger.info "Request: #{path}"
|
92
|
+
# result = @client.get(path, params = params.merge({
|
93
|
+
# :client_id => @config.client_id,
|
94
|
+
# :api_key => @config.api_key
|
95
|
+
# }))
|
96
|
+
# rescue Faraday::Error::ConnectionFailed => e
|
97
|
+
# # TODO this is suspect but because farady wraps the exception
|
98
|
+
# # in something generic there doesn't appear to be another
|
99
|
+
# # way to distinguish different connection errors :(
|
100
|
+
# if e.message =~ /certificate verify failed/
|
101
|
+
# raise Errors::CertificateError
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# raise e
|
105
|
+
# end
|
106
|
+
|
107
|
+
# # remove the api key in case an error gets dumped to the console
|
108
|
+
# params[:api_key] = 'REMOVED'
|
109
|
+
|
110
|
+
# begin
|
111
|
+
# body = JSON.parse(result.body)
|
112
|
+
# @logger.info "Response: #{body}"
|
113
|
+
# rescue JSON::ParserError => e
|
114
|
+
# raise(Errors::JSONError, {
|
115
|
+
# :message => e.message,
|
116
|
+
# :path => path,
|
117
|
+
# :params => params,
|
118
|
+
# :response => result.body
|
119
|
+
# })
|
120
|
+
# end
|
121
|
+
|
122
|
+
# if body['status'] != 'OK'
|
123
|
+
# raise(Errors::APIStatusError, {
|
124
|
+
# :path => path,
|
125
|
+
# :params => params,
|
126
|
+
# :status => body['status'],
|
127
|
+
# :response => body.inspect
|
128
|
+
# })
|
129
|
+
# end
|
130
|
+
|
131
|
+
# Result.new(body)
|
132
|
+
# end
|
133
|
+
|
134
|
+
# def wait_for_event(env, id)
|
135
|
+
# retryable(:tries => 120, :sleep => 10) do
|
136
|
+
# # stop waiting if interrupted
|
137
|
+
# next if env[:interrupted]
|
138
|
+
|
139
|
+
# check event status
|
140
|
+
# result = self.request("/events/#{id}")
|
141
|
+
|
142
|
+
# yield result if block_given?
|
143
|
+
# raise 'not ready' if result['event']['action_status'] != 'done'
|
144
|
+
# end
|
145
|
+
# end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Abiquo
|
3
|
+
module Helpers
|
4
|
+
class Result
|
5
|
+
def initialize(body)
|
6
|
+
@result = body
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
@result[key.to_s]
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_id(sub_obj, search)
|
14
|
+
find(sub_obj, search)["id"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def find(sub_obj, search)
|
18
|
+
key = search.keys.first
|
19
|
+
value = search[key].to_s
|
20
|
+
key = key.to_s
|
21
|
+
|
22
|
+
result = @result[sub_obj.to_s].inject(nil) do |result, obj|
|
23
|
+
obj[key] == value ? obj : result
|
24
|
+
end
|
25
|
+
|
26
|
+
result || error(sub_obj, key, value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def error(sub_obj, key, value)
|
30
|
+
raise(Errors::ResultMatchError, {
|
31
|
+
:key => key,
|
32
|
+
:value => value,
|
33
|
+
:collection_name => sub_obj.to_s,
|
34
|
+
:sub_obj => @result[sub_obj.to_s]
|
35
|
+
})
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|