vagrant_abiquo 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ require 'vagrant_abiquo/helpers/client'
2
+ require 'vagrant_abiquo/helpers/abiquo'
3
+
4
+ module VagrantPlugins
5
+ module Abiquo
6
+ module Actions
7
+ class CheckState
8
+ include Helpers::Client
9
+
10
+ def initialize(app, env)
11
+ @app = app
12
+ @machine = env[:machine]
13
+ @logger = Log4r::Logger.new('vagrant::abiquo::check_state')
14
+ end
15
+
16
+ def call(env)
17
+ env[:machine_state] = @machine.state.id
18
+ @logger.info "Machine state is '#{@machine.state.id}'"
19
+ @app.call(env)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,120 @@
1
+ require 'vagrant_abiquo/helpers/client'
2
+ require 'vagrant_abiquo/helpers/abiquo'
3
+
4
+ module VagrantPlugins
5
+ module Abiquo
6
+ module Actions
7
+ class Create
8
+ include Helpers::Client
9
+ include Helpers::Abiquo
10
+ include Vagrant::Util::Retryable
11
+
12
+ def initialize(app, env)
13
+ @app = app
14
+ @machine = env[:machine]
15
+ @client = client
16
+ @env = env
17
+ @logger = Log4r::Logger.new('vagrant::abiquo::create')
18
+ end
19
+
20
+ def call(env)
21
+ # Find for selected virtual datacenter
22
+ vdc = get_vdc(@machine.provider_config.virtualdatacenter)
23
+ raise Abiquo::Errors::VDCNotFound, vdc: @machine.provider_config.virtualdatacenter if vdc.nil?
24
+
25
+ # Find for selected virtual appliance
26
+ vname = vapp_name(@machine)
27
+ vapp = get_vapp(vdc, vname)
28
+
29
+ # Find for selected vm template
30
+ template = get_template(vdc, @machine.provider_config.template)
31
+ raise Abiquo::Errors::TemplateNotFound, template: @machine.provider_config.template, vdc: vdc.name if template.nil?
32
+
33
+ # If everything is OK we can proceed to create the VM
34
+ # VM Template link
35
+ tmpl_link = template.link(:edit).clone.to_hash
36
+ tmpl_link['rel'] = "virtualmachinetemplate"
37
+
38
+ # Configured CPU and RAM
39
+ cpu_cores = @machine.provider_config.cpu_cores
40
+ ram_mb = @machine.provider_config.ram_mb
41
+
42
+ # VM entity
43
+ vm_definition = {}
44
+ vm_definition['cpu'] = cpu_cores || template.cpuRequired
45
+ vm_definition['ram'] = ram_mb || template.ramRequired
46
+ vm_definition['label'] = @machine.name
47
+ vm_definition['vdrpEnabled'] = true
48
+ vm_definition['links'] = [ tmpl_link ]
49
+
50
+ # Create VM
51
+ env[:ui].info I18n.t('vagrant_abiquo.info.create')
52
+ vm = create_vm(vm_definition, vapp)
53
+
54
+ # User Data
55
+ md = vm.link(:metadata).get
56
+ mdhash = JSON.parse(md.to_json)
57
+ if mdhash['metadata'].nil?
58
+ mdhash['metadata'] = { 'startup-script' => @machine.provider_config.user_data }
59
+ else
60
+ mdhash['metadata']['startup-script'] = @machine.provider_config.user_data
61
+ end
62
+ @client.put(vm.link(:metadata), mdhash.to_json)
63
+
64
+ # Check network
65
+ unless @machine.provider_config.network.nil?
66
+ # Network config is not nil, so we have
67
+ # to attach a specific net.
68
+ attach_net(vm, @machine.provider_config.network)
69
+ raise Abiquo::Errors::NetworkError if vm.nil?
70
+ end
71
+ vm = vm.link(:edit).get
72
+
73
+ # Deploying VM
74
+ env[:ui].info I18n.t('vagrant_abiquo.info.deploy')
75
+ task = deploy(vm)
76
+
77
+ if task.state == 'FINISHED_SUCCESSFULLY'
78
+ # Deploy successfully completed
79
+ env[:ui].info I18n.t('vagrant_abiquo.info.deploycompleted')
80
+
81
+ # Give time to the OS to boot.
82
+ retryable(:tries => 20, :sleep => 5) do
83
+ next if env[:interrupted]
84
+ raise 'not ready' if !@machine.communicate.ready?
85
+ end
86
+
87
+ # Find its IP
88
+ vm = vm.link(:edit).get
89
+ ip = vm.link(:nic0).title
90
+ env[:ui].info I18n.t('vagrant_abiquo.info.vm_ip', :ip => ip)
91
+ @machine.id = vm.url
92
+ else
93
+ # Deploy failed
94
+ env[:ui].error I18n.t('vagrant_abiquo.info.deployfailed')
95
+ end
96
+
97
+ @app.call(env)
98
+ end
99
+
100
+ # Both the recover and terminate are stolen almost verbatim from
101
+ # the Vagrant AWS provider up action
102
+ def recover(env)
103
+ return if env['vagrant.error'].is_a?(Vagrant::Errors::VagrantError)
104
+
105
+ if @machine.state.id != :not_created
106
+ terminate(env)
107
+ end
108
+ end
109
+
110
+ def terminate(env)
111
+ destroy_env = env.dup
112
+ destroy_env.delete(:interrupted)
113
+ destroy_env[:config_validate] = false
114
+ destroy_env[:force_confirm_destroy] = true
115
+ env[:action_runner].run(Actions.destroy, destroy_env)
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,38 @@
1
+ require 'vagrant_abiquo/helpers/client'
2
+ require 'vagrant_abiquo/helpers/abiquo'
3
+
4
+ module VagrantPlugins
5
+ module Abiquo
6
+ module Actions
7
+ class CreatevApp
8
+ include Helpers::Client
9
+ include Helpers::Abiquo
10
+
11
+ def initialize(app, env)
12
+ @app = app
13
+ @machine = env[:machine]
14
+ @logger = Log4r::Logger.new('vagrant::abiquo::create_vapp')
15
+ end
16
+
17
+ def call(env)
18
+ pconfig = env[:env].vagrantfile.config.finalize![:vm].get_provider_config(:abiquo)
19
+ @client ||= AbiquoAPI.new(pconfig.abiquo_connection_data)
20
+
21
+ @logger.info "Checking vApp '#{pconfig.virtualappliance}'"
22
+
23
+ @logger.info "Looking up VDC '#{pconfig.virtualdatacenter}'"
24
+ vdc = get_vdc(pconfig.virtualdatacenter)
25
+ raise Abiquo::Errors::VDCNotFound, vdc: pconfig.virtualdatacenter if vdc.nil?
26
+
27
+ vapp = get_vapp(vdc, pconfig.virtualappliance)
28
+ if vapp.nil?
29
+ @logger.info "vApp '#{pconfig.virtualappliance}' does not exist, creating."
30
+ create_vapp(vdc, pconfig.virtualappliance)
31
+ end
32
+
33
+ @app.call(env)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,46 @@
1
+ require 'vagrant_abiquo/helpers/client'
2
+ require 'vagrant_abiquo/helpers/abiquo'
3
+
4
+ module VagrantPlugins
5
+ module Abiquo
6
+ module Actions
7
+ class Destroy
8
+ include Helpers::Client
9
+ include Helpers::Abiquo
10
+ include Vagrant::Util::Retryable
11
+
12
+ def initialize(app, env)
13
+ @app = app
14
+ @machine = env[:machine]
15
+ @client = client
16
+ @logger = Log4r::Logger.new('vagrant::abiquo::destroy')
17
+ end
18
+
19
+ def call(env)
20
+ env[:ui].info I18n.t('vagrant_abiquo.info.destroying', vm: @machine.name)
21
+ vm = get_vm(@machine.id)
22
+ vm.delete
23
+
24
+ # Check when task finishes. This may take a while
25
+ retryable(:tries => 120, :sleep => 5) do
26
+ begin
27
+ raise vm.label if vm.refresh
28
+ rescue AbiquoAPIClient::NotFound
29
+ env[:ui].info I18n.t('vagrant_abiquo.info.deleted', vm: @machine.name)
30
+ end
31
+ end
32
+
33
+ vapp = vm.link(:virtualappliance).get
34
+ vms = vapp.link(:virtualmachines).get.count
35
+ if vms == 0
36
+ vapp.delete
37
+ env[:ui].info I18n.t('vagrant_abiquo.info.deleted_vapp', vapp: vapp.name)
38
+ end
39
+
40
+ @machine.id = nil
41
+ @app.call(env)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,30 @@
1
+ require 'vagrant_abiquo/helpers/client'
2
+ require 'vagrant_abiquo/helpers/abiquo'
3
+
4
+ module VagrantPlugins
5
+ module Abiquo
6
+ module Actions
7
+ class PowerOff
8
+ include Helpers::Client
9
+ include Helpers::Abiquo
10
+ include Vagrant::Util::Retryable
11
+
12
+ def initialize(app, env)
13
+ @app = app
14
+ @machine = env[:machine]
15
+ @client = AbiquoAPI.new(@machine.provider_config.abiquo_connection_data)
16
+ @logger = Log4r::Logger.new('vagrant::abiquo::power_off')
17
+ end
18
+
19
+ def call(env)
20
+ vm = get_vm(@machine.id)
21
+ vm = power_off(vm)
22
+ raise PowerOffError, vm: vm.label, state: vm.state if vm.state != 'OFF'
23
+
24
+ @app.call(env)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,30 @@
1
+ require 'vagrant_abiquo/helpers/client'
2
+ require 'vagrant_abiquo/helpers/abiquo'
3
+
4
+ module VagrantPlugins
5
+ module Abiquo
6
+ module Actions
7
+ class PowerOn
8
+ include Helpers::Client
9
+ include Helpers::Abiquo
10
+ include Vagrant::Util::Retryable
11
+
12
+ def initialize(app, env)
13
+ @app = app
14
+ @machine = env[:machine]
15
+ @client = AbiquoAPI.new(@machine.provider_config.abiquo_connection_data)
16
+ @logger = Log4r::Logger.new('vagrant::abiquo::power_off')
17
+ end
18
+
19
+ def call(env)
20
+ vm = get_vm(@machine.id)
21
+ vm = poweron(vm)
22
+ raise PowerOnError, vm: vm.label, state: vm.state if vm.state != 'ON'
23
+
24
+ @app.call(env)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,37 @@
1
+ require 'vagrant_abiquo/helpers/client'
2
+ require 'vagrant_abiquo/helpers/abiquo'
3
+
4
+ module VagrantPlugins
5
+ module Abiquo
6
+ module Actions
7
+ class Reset
8
+ include Helpers::Client
9
+ include Helpers::Abiquo
10
+ include Vagrant::Util::Retryable
11
+
12
+ def initialize(app, env)
13
+ @app = app
14
+ @machine = env[:machine]
15
+ @client = AbiquoAPI.new(@machine.provider_config.abiquo_connection_data)
16
+ @logger = Log4r::Logger.new('vagrant::abiquo::reset')
17
+ end
18
+
19
+ def call(env)
20
+ env[:ui].info I18n.t('vagrant_abiquo.info.reloading')
21
+ vm = get_vm(@machine.id)
22
+ vm = reset(vm)
23
+
24
+ # Give time to the OS to boot.
25
+ retryable(:tries => 120, :sleep => 10) do
26
+ next if env[:interrupted]
27
+ raise 'not ready' if !@machine.communicate.ready?
28
+ end
29
+
30
+ @app.call(env)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+
@@ -0,0 +1,55 @@
1
+ module VagrantPlugins
2
+ module Abiquo
3
+ class Config < Vagrant.plugin('2', :config)
4
+ attr_accessor :abiquo_connection_data
5
+ attr_accessor :virtualdatacenter
6
+ attr_accessor :virtualappliance
7
+ attr_accessor :cpu_cores
8
+ attr_accessor :ram_mb
9
+ attr_accessor :template
10
+ attr_accessor :network
11
+ attr_accessor :user_data
12
+
13
+ def initialize
14
+ @abiquo_connection_data = UNSET_VALUE
15
+ @virtualdatacenter = UNSET_VALUE
16
+ @virtualappliance = UNSET_VALUE
17
+ @template = UNSET_VALUE
18
+ @cpu_cores = 0
19
+ @ram_mb = 0
20
+ @network = UNSET_VALUE
21
+ @user_data = UNSET_VALUE
22
+ end
23
+
24
+ def finalize!
25
+ @abiquo_connection_data[:abiquo_api_url] = ENV['ABQ_URL'] if @abiquo_connection_data[:abiquo_api_url].nil?
26
+ @abiquo_connection_data[:abiquo_username] = ENV['ABQ_USER'] if @abiquo_connection_data[:abiquo_username].nil?
27
+ @abiquo_connection_data[:abiquo_password] = ENV['ABQ_PASS'] if @abiquo_connection_data[:abiquo_password].nil?
28
+
29
+ @virtualdatacenter = ENV['ABQ_VDC'] if @virtualdatacenter == UNSET_VALUE
30
+ @virtualappliance = ENV['ABQ_VAPP'] if @virtualappliance == UNSET_VALUE
31
+ @template = ENV['ABQ_TMPL'] if @template == UNSET_VALUE
32
+
33
+ @cpu_cores = ENV['ABQ_CPU'] if @cpu_cores == 0
34
+ @ram_mb = ENV['ABQ_RAM'] if @ram_mb == 0
35
+ @ram_mb = nil if @ram_mb == 0
36
+
37
+ @network = { ENV['ABQ_NET'] => ENV['ABQ_IP'] } if @network == UNSET_VALUE
38
+
39
+ if @user_data == UNSET_VALUE
40
+ # We will make sure the SSH key is injected.
41
+ @user_data = '#!/bin/bash\necho "vagrant_abiquo :: making sure SSH key gets injected."'
42
+ end
43
+ end
44
+
45
+ def validate(machine)
46
+ errors = []
47
+ errors << I18n.t('vagrant_abiquo.config.abiquo_connection_data') if !@abiquo_connection_data
48
+ errors << I18n.t('vagrant_abiquo.config.virtualdatacenter') if !@virtualdatacenter
49
+ errors << I18n.t('vagrant_abiquo.config.template') if !@template
50
+
51
+ { 'Abiquo Provider' => errors }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,45 @@
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 VDCNotFound < AbiquoError
9
+ error_key(:vdc_not_found)
10
+ end
11
+
12
+ class TemplateNotFound < AbiquoError
13
+ error_key(:template_not_found)
14
+ end
15
+
16
+ class PowerOffError < AbiquoError
17
+ error_key(:poweroff_error)
18
+ end
19
+
20
+ class NetworkError < AbiquoError
21
+ error_key(:network_error)
22
+ end
23
+
24
+ class APIStatusError < AbiquoError
25
+ error_key(:api_status)
26
+ end
27
+
28
+ class APIFindError < AbiquoError
29
+ error_key(:apifind_error)
30
+ end
31
+
32
+ class JSONError < AbiquoError
33
+ error_key(:json)
34
+ end
35
+
36
+ class ResultMatchError < AbiquoError
37
+ error_key(:result_match)
38
+ end
39
+
40
+ class LocalIPError < AbiquoError
41
+ error_key(:local_ip)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,173 @@
1
+ require 'abiquo-api'
2
+ require 'log4r'
3
+ include Log4r
4
+
5
+ module VagrantPlugins
6
+ module Abiquo
7
+ module Helpers
8
+ module Abiquo
9
+ include Helpers::Client
10
+
11
+ @logger = Log4r::Logger.new('vagrant::abiquo::helper')
12
+
13
+ def vapp_name(machine)
14
+ machine.provider_config.virtualappliance.nil? ? File.basename(machine.env.cwd) : machine.provider_config.virtualappliance
15
+ end
16
+
17
+ def get_vm(vm_url)
18
+ vm_lnk = AbiquoAPI::Link.new :href => vm_url,
19
+ :type => 'application/vnd.abiquo.virtualmachine+json',
20
+ :client => client
21
+ vm_lnk.get
22
+ end
23
+
24
+ def get_vdc(vdc_name)
25
+ vdcs_lnk = AbiquoAPI::Link.new :href => 'cloud/virtualdatacenters',
26
+ :type => "application/vnd.abiquo.virtualdatacenters+json",
27
+ :client => client
28
+ vdcs_lnk.get.select {|vd| vd.name == vdc_name }.first
29
+ end
30
+
31
+ def get_vapp(vdc, name)
32
+ vdc.link(:virtualappliances).get.select {|va| va.name == name }.first
33
+ end
34
+
35
+ def create_vapp(vdc, name)
36
+ vapp_hash = { 'name' => name }
37
+ client.post(vdc.link(:virtualappliances), vapp_hash.to_json,
38
+ accept: 'application/vnd.abiquo.virtualappliance+json',
39
+ content: 'application/vnd.abiquo.virtualappliance+json')
40
+ end
41
+
42
+ def get_template(vdc, template)
43
+ vdc.link(:templates).get.select {|tmpl| tmpl.name == template }.first
44
+ end
45
+
46
+ def get_network(vm, net_name)
47
+ vdc = vm.link(:virtualdatacenter).get
48
+
49
+ networks = []
50
+ %w(privatenetworks network externalnetworks).each do |nettype|
51
+ begin
52
+ vdc.link(nettype.to_sym).get.each {|n| networks << n}
53
+ rescue Exception => e
54
+ @logger.debug "Exception retrieving '#{nettype}' networks."
55
+ @logger.debug e.message
56
+ @logger.debug e.backtrace
57
+ end
58
+ end
59
+ networks.select {|n| n.name == net_name }.first
60
+ end
61
+
62
+ def create_vm(vm_def, vapp)
63
+ client.post(vapp.link(:virtualmachines), vm_def.to_json,
64
+ :content => "application/vnd.abiquo.virtualmachine+json",
65
+ :accept => "application/vnd.abiquo.virtualmachine+json" )
66
+ end
67
+
68
+ def attach_net(vm, net_data)
69
+ net_data.each do |net, ip|
70
+ network = get_network(vm, net)
71
+ return nil if network.nil?
72
+
73
+ if ip
74
+ abqip = network.link(:ips).get.select {|i| i.ip == ip }.first
75
+ else
76
+ abqip = network.link(:ips).get.select {|i| ! i.has_link? :virtualmachine }.first
77
+ end
78
+
79
+ if abqip.nil?
80
+ if network.type == "EXTERNAL" || network.type == "PUBLIC"
81
+ # Can't create IP in those nets
82
+ return nil
83
+ end
84
+
85
+ # We have the net, we don't have the IP, create it
86
+ ip_hash = {
87
+ "ipv6" => network.ipv6,
88
+ "available" => true,
89
+ "quarantine" => false,
90
+ "numips" => 1,
91
+ "ip" => ip
92
+ }
93
+ abqip = client.post(network.link(:ips), ip_hash.to_json,
94
+ :accept => 'application/vnd.abiquo.privateip+json',
95
+ :content => 'application/vnd.abiquo.privateip+json' )
96
+ end
97
+
98
+ ip_lnk = abqip.link(:self).clone
99
+ ip_lnk.rel = 'nic0'
100
+ vm.links << {:nic0 => ip_lnk}
101
+
102
+ update(vm)
103
+ end
104
+ end
105
+
106
+ def deploy(vm)
107
+ task_lnk = client.post(vm.link(:deploy), '').link(:status).href
108
+ task = AbiquoAPI::Link.new(:href => task_lnk,
109
+ :type => 'application/vnd.abiquo.task+json',
110
+ :client => client).get
111
+
112
+ # Check when deploy finishes. This may take a while
113
+ retryable(:tries => 120, :sleep => 15) do
114
+ task = task.link(:self).get
115
+ raise vm.label if task.state == 'STARTED'
116
+ end
117
+
118
+ task
119
+ end
120
+
121
+ def apply_state(vm, state)
122
+ task_lnk = client.put(vm.link(:state), {"state" => state}.to_json,
123
+ :accept => 'application/vnd.abiquo.acceptedrequest+json',
124
+ :content => 'application/vnd.abiquo.virtualmachinestate+json').link(:status)
125
+ task = task_lnk.get
126
+
127
+ # Check when task finishes. This may take a while
128
+ retryable(:tries => 120, :sleep => 5) do
129
+ task = task.link(:self).get
130
+ raise vm.label if task.state == 'STARTED'
131
+ end
132
+ vm.link(:edit).get
133
+ end
134
+
135
+ def poweroff(vm)
136
+ apply_state('OFF')
137
+ end
138
+
139
+ def poweron(vm)
140
+ apply_state('ON')
141
+ end
142
+
143
+ def reset(vm)
144
+ task = client.post(vm.link(:reset), '',
145
+ :accept => 'application/vnd.abiquo.acceptedrequest+json',
146
+ :content => 'application/json').link(:status).get
147
+
148
+ # Check when task finishes. This may take a while
149
+ retryable(:tries => 120, :sleep => 5) do
150
+ task = task.link(:self).get
151
+ raise vm.label if task.state == 'STARTED'
152
+ end
153
+ vm.link(:edit).get
154
+ end
155
+
156
+ def update(vm)
157
+ task = client.put(vm.link(:edit), vm.to_json,
158
+ :accept => 'application/vnd.abiquo.acceptedrequest+json',
159
+ :content => vm.link(:edit).type)
160
+ if task
161
+ task = task.link(:status).get
162
+ # Check when task finishes. This may take a while
163
+ retryable(:tries => 120, :sleep => 5) do
164
+ task = task.link(:self).get
165
+ raise vm.label if task.state == 'STARTED'
166
+ end
167
+ end
168
+ vm.link(:edit).get
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end