vagrant-1cloud 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/Gemfile +10 -0
- data/LICENSE +373 -0
- data/Rakefile +22 -0
- data/lib/vagrant-1cloud.rb +14 -0
- data/lib/vagrant-1cloud/actions.rb +138 -0
- data/lib/vagrant-1cloud/actions/check_state.rb +19 -0
- data/lib/vagrant-1cloud/actions/create.rb +70 -0
- data/lib/vagrant-1cloud/actions/destroy.rb +30 -0
- data/lib/vagrant-1cloud/actions/power_off.rb +35 -0
- data/lib/vagrant-1cloud/actions/power_on.rb +36 -0
- data/lib/vagrant-1cloud/actions/reload.rb +33 -0
- data/lib/vagrant-1cloud/actions/shut_down.rb +35 -0
- data/lib/vagrant-1cloud/config.rb +46 -0
- data/lib/vagrant-1cloud/errors.rb +33 -0
- data/lib/vagrant-1cloud/helpers/client.rb +83 -0
- data/lib/vagrant-1cloud/helpers/result.rb +40 -0
- data/lib/vagrant-1cloud/plugin.rb +21 -0
- data/lib/vagrant-1cloud/provider.rb +67 -0
- data/lib/vagrant-1cloud/version.rb +5 -0
- data/locales/en.yml +67 -0
- data/test/Vagrantfile +16 -0
- data/test/scripts/provision.sh +3 -0
- data/test/test.sh +9 -0
- data/vagrant-1cloud.gemspec +21 -0
- metadata +113 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module OneCloud
|
3
|
+
module Actions
|
4
|
+
class CheckState
|
5
|
+
def initialize(app, env)
|
6
|
+
@app = app
|
7
|
+
@machine = env[:machine]
|
8
|
+
@logger = Log4r::Logger.new('vagrant::1cloud::check_state')
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:machine_state] = @machine.state.id
|
13
|
+
@logger.info "Machine state is '#{@machine.state.id}'"
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'vagrant-1cloud/helpers/client'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OneCloud
|
5
|
+
module Actions
|
6
|
+
class Create
|
7
|
+
include Helpers::Client
|
8
|
+
include Vagrant::Util::Retryable
|
9
|
+
|
10
|
+
def initialize(app, env)
|
11
|
+
@app = app
|
12
|
+
@machine = env[:machine]
|
13
|
+
@client = client
|
14
|
+
@logger = Log4r::Logger.new('vagrant::1cloud::create')
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
# submit new droplet request
|
19
|
+
result = @clientservice.post('/server', {
|
20
|
+
:HDD => @machine.provider_config.hdd,
|
21
|
+
:HDDType => @machine.provider_config.hdd_type,
|
22
|
+
:CPU => @machine.provider_config.cpu,
|
23
|
+
:RAM => @machine.provider_config.ram,
|
24
|
+
:DCLocation => @machine.provider_config.region,
|
25
|
+
:ImageID => @machine.provider_config.image,
|
26
|
+
:Name => @machine.config.vm.hostname || @machine.name,
|
27
|
+
:isHighPerformance => @machine.provider_config.hi_perf
|
28
|
+
})
|
29
|
+
|
30
|
+
# assign the machine id for reference in other commands
|
31
|
+
@machine.id = result['id'].to_s
|
32
|
+
|
33
|
+
# wait for request to complete
|
34
|
+
result = @client.request("/server/#{@machine.id}/action")
|
35
|
+
env[:ui].info I18n.t('vagrant_1cloud.info.creating')
|
36
|
+
@client.wait_for_event(env, @machine.id, result.first['ID'])
|
37
|
+
|
38
|
+
# refresh droplet state with provider
|
39
|
+
droplet = Provider.droplet(@machine, :refresh => true)
|
40
|
+
|
41
|
+
# wait for ssh to be ready
|
42
|
+
retryable(:tries => 120, :sleep => 10) do
|
43
|
+
next if env[:interrupted]
|
44
|
+
raise 'not ready' if !@machine.communicate.ready?
|
45
|
+
end
|
46
|
+
|
47
|
+
@app.call(env)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Both the recover and terminate are stolen almost verbatim from
|
51
|
+
# the Vagrant AWS provider up action
|
52
|
+
# def recover(env)
|
53
|
+
# return if env['vagrant.error'].is_a?(Vagrant::Errors::VagrantError)
|
54
|
+
|
55
|
+
# if @machine.state.id != :not_created
|
56
|
+
# terminate(env)
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
|
60
|
+
# def terminate(env)
|
61
|
+
# destroy_env = env.dup
|
62
|
+
# destroy_env.delete(:interrupted)
|
63
|
+
# destroy_env[:config_validate] = false
|
64
|
+
# destroy_env[:force_confirm_destroy] = true
|
65
|
+
# env[:action_runner].run(Actions.destroy, destroy_env)
|
66
|
+
# end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'vagrant-1cloud/helpers/client'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OneCloud
|
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::1cloud::destroy')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# submit destroy droplet request
|
18
|
+
@client.delete("/server/#{@machine.id}")
|
19
|
+
|
20
|
+
env[:ui].info I18n.t('vagrant_1cloud.info.destroying')
|
21
|
+
|
22
|
+
# set the machine id to nil to cleanup local vagrant state
|
23
|
+
@machine.id = nil
|
24
|
+
|
25
|
+
@app.call(env)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'vagrant-1cloud/helpers/client'
|
2
|
+
#TODO: --force
|
3
|
+
module VagrantPlugins
|
4
|
+
module OneCloud
|
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::1cloud::power_off')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# submit power off droplet request
|
18
|
+
result = @client.post("/server/#{@machine.id}/action", {
|
19
|
+
:Type => 'PowerOff'
|
20
|
+
})
|
21
|
+
|
22
|
+
# wait for request to complete
|
23
|
+
env[:ui].info I18n.t('vagrant_1cloud.info.powering_off')
|
24
|
+
@client.wait_for_event(env, @machine.id, result['ID'])
|
25
|
+
|
26
|
+
# refresh droplet state with provider
|
27
|
+
Provider.droplet(@machine, :refresh => true)
|
28
|
+
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'vagrant-1cloud/helpers/client'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OneCloud
|
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::1cloud::power_on')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# submit power on droplet request
|
18
|
+
result = @client.post("/server/#{@machine.id}/action", {
|
19
|
+
:Type => 'PowerOn'
|
20
|
+
})
|
21
|
+
|
22
|
+
# wait for request to complete
|
23
|
+
env[:ui].info I18n.t('vagrant_1cloud.info.powering_on')
|
24
|
+
@client.wait_for_event(env, @machine.id, result['ID'])
|
25
|
+
|
26
|
+
# refresh droplet state with provider
|
27
|
+
Provider.droplet(@machine, :refresh => true)
|
28
|
+
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'vagrant-1cloud/helpers/client'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OneCloud
|
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::1cloud::reload')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# submit reboot droplet request
|
18
|
+
result = @client.post("/server/#{@machine.id}/action", {
|
19
|
+
:Type => 'PowerReboot'
|
20
|
+
})
|
21
|
+
|
22
|
+
# wait for request to complete
|
23
|
+
env[:ui].info I18n.t('vagrant_1cloud.info.reloading')
|
24
|
+
@client.wait_for_event(env, @machine.id, result['ID'])
|
25
|
+
|
26
|
+
@app.call(env)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'vagrant-1cloud/helpers/client'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module OneCloud
|
5
|
+
module Actions
|
6
|
+
class ShutDown
|
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::1cloud::shut_down')
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
# submit shutdown droplet request
|
18
|
+
result = @client.post("/server/#{@machine.id}/action", {
|
19
|
+
:Type => 'ShutDownGuestOS'
|
20
|
+
})
|
21
|
+
|
22
|
+
# wait for request to complete
|
23
|
+
env[:ui].info I18n.t('vagrant_1cloud.info.shutting_down')
|
24
|
+
@client.wait_for_event(env, @machine.id, result['ID'])
|
25
|
+
|
26
|
+
# refresh droplet state with provider
|
27
|
+
Provider.droplet(@machine, :refresh => true)
|
28
|
+
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module OneCloud
|
3
|
+
class Config < Vagrant.plugin('2', :config)
|
4
|
+
attr_accessor :token
|
5
|
+
attr_accessor :image
|
6
|
+
attr_accessor :region
|
7
|
+
attr_accessor :hdd
|
8
|
+
attr_accessor :hdd_type
|
9
|
+
attr_accessor :cpu
|
10
|
+
attr_accessor :ram
|
11
|
+
attr_accessor :hi_perf
|
12
|
+
attr_accessor :ca_path
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@token = UNSET_VALUE
|
16
|
+
@image = UNSET_VALUE
|
17
|
+
@region = UNSET_VALUE
|
18
|
+
@hdd = UNSET_VALUE
|
19
|
+
@hdd_type = UNSET_VALUE
|
20
|
+
@cpu = UNSET_VALUE
|
21
|
+
@ram = UNSET_VALUE
|
22
|
+
@hi_perf = UNSET_VALUE
|
23
|
+
@ca_path = UNSET_VALUE
|
24
|
+
end
|
25
|
+
|
26
|
+
def finalize!
|
27
|
+
@token = ENV['DO_TOKEN'] if @token == UNSET_VALUE
|
28
|
+
@image = '7' if @image == UNSET_VALUE
|
29
|
+
@region = 'SDN_SPb' if @region == UNSET_VALUE
|
30
|
+
@hdd = '1' if @hdd == UNSET_VALUE
|
31
|
+
@hdd_type = 'SAS' if @hdd_type == UNSET_VALUE
|
32
|
+
@cpu = '1' if @cpu == UNSET_VALUE
|
33
|
+
@ram = '512' if @ram == UNSET_VALUE
|
34
|
+
@hi_perf = false if @hi_perf == UNSET_VALUE
|
35
|
+
@ca_path = nil if @ca_path == UNSET_VALUE
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate(machine)
|
39
|
+
errors = []
|
40
|
+
errors << I18n.t('vagrant_1cloud.config.token') if !@token
|
41
|
+
|
42
|
+
{ '1cloud Provider' => errors }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module OneCloud
|
3
|
+
module Errors
|
4
|
+
class OneCloudError < Vagrant::Errors::VagrantError
|
5
|
+
error_namespace("vagrant_1cloud.errors")
|
6
|
+
end
|
7
|
+
|
8
|
+
class APIStatusError < OneCloudError
|
9
|
+
error_key(:api_status)
|
10
|
+
end
|
11
|
+
|
12
|
+
class JSONError < OneCloudError
|
13
|
+
error_key(:json)
|
14
|
+
end
|
15
|
+
|
16
|
+
class ResultMatchError < OneCloudError
|
17
|
+
error_key(:result_match)
|
18
|
+
end
|
19
|
+
|
20
|
+
class CertificateError < OneCloudError
|
21
|
+
error_key(:certificate)
|
22
|
+
end
|
23
|
+
|
24
|
+
class LocalIPError < OneCloudError
|
25
|
+
error_key(:local_ip)
|
26
|
+
end
|
27
|
+
|
28
|
+
class RsyncError < OneCloudError
|
29
|
+
error_key(:rsync)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'vagrant-1cloud/helpers/result'
|
2
|
+
require 'faraday'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module OneCloud
|
7
|
+
module Helpers
|
8
|
+
module Client
|
9
|
+
def client
|
10
|
+
@client ||= ApiClient.new(@machine)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ApiClient
|
15
|
+
include Vagrant::Util::Retryable
|
16
|
+
|
17
|
+
def initialize(machine)
|
18
|
+
@logger = Log4r::Logger.new('vagrant::1cloud::apiclient')
|
19
|
+
@config = machine.provider_config
|
20
|
+
@client = Faraday.new({
|
21
|
+
:url => 'https://api.1cloud.ru/',
|
22
|
+
:ssl => {
|
23
|
+
:ca_file => @config.ca_path
|
24
|
+
}
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
def delete(path, params = {}, method = :delete)
|
29
|
+
@client.request :url_encoded
|
30
|
+
request(path, params, :delete)
|
31
|
+
end
|
32
|
+
|
33
|
+
def post(path, params = {}, method = :post)
|
34
|
+
@client.headers['Content-Type'] = 'application/json'
|
35
|
+
request(path, params, :post)
|
36
|
+
end
|
37
|
+
|
38
|
+
def request(path, params = {}, method = :get)
|
39
|
+
begin
|
40
|
+
@logger.info "Request: #{path}"
|
41
|
+
result = @client.send(method) do |req|
|
42
|
+
req.url path
|
43
|
+
req.headers['Authorization'] = "Bearer #{@config.token}"
|
44
|
+
req.body = params.to_json
|
45
|
+
end
|
46
|
+
rescue Faraday::Error::ConnectionFailed => e
|
47
|
+
# TODO this is suspect but because faraday wraps the exception
|
48
|
+
# in something generic there doesn't appear to be another
|
49
|
+
# way to distinguish different connection errors :(
|
50
|
+
if e.message =~ /certificate verify failed/
|
51
|
+
raise Errors::CertificateError
|
52
|
+
end
|
53
|
+
raise e
|
54
|
+
end
|
55
|
+
|
56
|
+
unless /^2\d\d$/ =~ result.status.to_s
|
57
|
+
raise(Errors::APIStatusError, {
|
58
|
+
:path => path,
|
59
|
+
:params => params,
|
60
|
+
:status => result.status,
|
61
|
+
:response => body.inspect
|
62
|
+
})
|
63
|
+
end
|
64
|
+
|
65
|
+
Result.new(result)
|
66
|
+
end
|
67
|
+
|
68
|
+
def wait_for_event(env, m_id, id)
|
69
|
+
retryable(:tries => 120, :sleep => 10) do
|
70
|
+
# stop waiting if interrupted
|
71
|
+
next if env[:interrupted]
|
72
|
+
|
73
|
+
# check action status
|
74
|
+
result = self.request("/server/#{m_id}/action/#{id}")
|
75
|
+
|
76
|
+
yield result if block_given?
|
77
|
+
raise 'not ready' if result['State'] != 'Completed'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module OneCloud
|
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
|