dopv 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/ChangeLog.md +456 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +260 -0
- data/Guardfile +22 -0
- data/LICENSE.txt +177 -0
- data/README.md +214 -0
- data/Rakefile +6 -0
- data/bin/dopv +4 -0
- data/dopv.gemspec +52 -0
- data/lib/dopv.rb +166 -0
- data/lib/dopv/cli.rb +54 -0
- data/lib/dopv/cli/command_add.rb +37 -0
- data/lib/dopv/cli/command_export.rb +26 -0
- data/lib/dopv/cli/command_import.rb +32 -0
- data/lib/dopv/cli/command_list.rb +18 -0
- data/lib/dopv/cli/command_remove.rb +29 -0
- data/lib/dopv/cli/command_run.rb +38 -0
- data/lib/dopv/cli/command_update.rb +35 -0
- data/lib/dopv/cli/command_validate.rb +30 -0
- data/lib/dopv/infrastructure.rb +40 -0
- data/lib/dopv/infrastructure/providers/baremetal.rb +12 -0
- data/lib/dopv/infrastructure/providers/base.rb +422 -0
- data/lib/dopv/infrastructure/providers/openstack.rb +308 -0
- data/lib/dopv/infrastructure/providers/ovirt.rb +228 -0
- data/lib/dopv/infrastructure/providers/vsphere.rb +322 -0
- data/lib/dopv/log.rb +14 -0
- data/lib/dopv/persistent_disk.rb +128 -0
- data/lib/dopv/plan.rb +17 -0
- data/lib/dopv/state_store.rb +87 -0
- data/lib/dopv/version.rb +3 -0
- data/spec/data/hooks/test_hook_script_1 +9 -0
- data/spec/data/hooks/test_hook_script_2 +10 -0
- data/spec/data/plans/test-plan-1.yaml +140 -0
- data/spec/spec_helper.rb +112 -0
- data/spec/unit/dopv/dopv_spec.rb +7 -0
- data/spec/unit/dopv/persistent_disk_spec.rb +38 -0
- data/spec/unit/dopv/plan_spec.rb +34 -0
- data/spec/unit/dopv/version_spec.rb +17 -0
- metadata +401 -0
@@ -0,0 +1,308 @@
|
|
1
|
+
require 'fog'
|
2
|
+
|
3
|
+
module Dopv
|
4
|
+
module Infrastructure
|
5
|
+
class OpenStack < Base
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegator :@plan, :flavor, :flavor_name
|
9
|
+
|
10
|
+
def initialize(node_config, data_disks_db)
|
11
|
+
super(node_config, data_disks_db)
|
12
|
+
|
13
|
+
|
14
|
+
@compute_connection_opts = {
|
15
|
+
:provider => 'openstack',
|
16
|
+
:openstack_username => provider_username,
|
17
|
+
:openstack_api_key => provider_password,
|
18
|
+
:openstack_project_name => provider_tenant,
|
19
|
+
:openstack_domain_id => provider_domain_id,
|
20
|
+
:openstack_auth_url => provider_url,
|
21
|
+
:openstack_endpoint_type => provider_endpoint_type,
|
22
|
+
:connection_options => {
|
23
|
+
:ssl_verify_peer => false,
|
24
|
+
#:debug_request => true
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
@network_connection_opts = @compute_connection_opts
|
29
|
+
@volume_connection_opts = @compute_connection_opts
|
30
|
+
|
31
|
+
@node_creation_opts = {
|
32
|
+
:name => nodename,
|
33
|
+
:image_ref => template.id,
|
34
|
+
:flavor_ref => flavor.id,
|
35
|
+
:config_drive => use_config_drive?,
|
36
|
+
:security_groups => security_groups
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def provider_tenant
|
43
|
+
@provider_tenant ||= infrastructure_properties.tenant
|
44
|
+
end
|
45
|
+
|
46
|
+
def provider_domain_id
|
47
|
+
@provider_domain_id ||= infrastructure_properties.domain_id
|
48
|
+
end
|
49
|
+
|
50
|
+
def provider_endpoint_type
|
51
|
+
@provider_endpoint_type ||= infrastructure_properties.endpoint_type
|
52
|
+
end
|
53
|
+
|
54
|
+
def use_config_drive?
|
55
|
+
@use_config_drive ||= infrastructure_properties.use_config_drive?
|
56
|
+
end
|
57
|
+
|
58
|
+
def security_groups
|
59
|
+
@security_groups ||= infrastructure_properties.security_groups
|
60
|
+
end
|
61
|
+
|
62
|
+
def network_provider
|
63
|
+
Dopv::log.info("Node #{nodename}: Creating network provider.") unless @network_provider
|
64
|
+
@network_provider ||= @network_connection_opts ? ::Fog::Network.new(@network_connection_opts) : nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def flavor(filters={})
|
68
|
+
@flavor ||= compute_provider.flavors(filters).find { |f| f.name == flavor_name }
|
69
|
+
raise ProviderError, "No such flavor #{flavor_name}" unless @flavor
|
70
|
+
@flavor
|
71
|
+
end
|
72
|
+
|
73
|
+
def network(name, filters={})
|
74
|
+
net = network_provider.networks(filters).find { |n| n.name == name || n.id == name }
|
75
|
+
raise ProviderError, "No such network #{name}" unless net
|
76
|
+
net
|
77
|
+
end
|
78
|
+
|
79
|
+
def subnet(name, filters={})
|
80
|
+
net = network_provider.subnets(filters).find { |s| s.name == name || s.id == name }
|
81
|
+
raise ProviderError, "No such subnetwork #{name}" unless net
|
82
|
+
net
|
83
|
+
end
|
84
|
+
|
85
|
+
def assign_security_groups(node_instance)
|
86
|
+
unless security_groups.empty?
|
87
|
+
Dopv::log.info("Node #{nodename}: Assigning security groups.")
|
88
|
+
config_sgs = security_groups.dup
|
89
|
+
node_instance.security_groups.uniq { |g| g.id }.each do |sg|
|
90
|
+
# Remove the security group from configuration if it is already
|
91
|
+
# assigned to an instance.
|
92
|
+
if config_sgs.delete(sg.name)
|
93
|
+
Dopv::log.debug("Node #{nodename}: Already assigned to security group #{sg.name}.")
|
94
|
+
next
|
95
|
+
end
|
96
|
+
# Remove the security group assignment if it isn't in the
|
97
|
+
# configuration.
|
98
|
+
unless config_sgs.include?(sg.name)
|
99
|
+
Dopv::log.debug("Node #{nodename}: Removing unneeded security group #{sg.name}.")
|
100
|
+
compute_provider.remove_security_group(node_instance.id, sg.name)
|
101
|
+
wait_for_task_completion(node_instance)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
# Add remaining security groups defined in config array.
|
105
|
+
config_sgs.each do |sg_name|
|
106
|
+
begin
|
107
|
+
Dopv::log.debug("Node #{nodename}: Adding security group #{sg_name}.")
|
108
|
+
compute_provider.add_security_group(node_instance.id, sg_name)
|
109
|
+
wait_for_task_completion(node_instance)
|
110
|
+
rescue
|
111
|
+
raise ProviderError, "An error occured while assigning security group #{sg_name}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
node_instance.reload
|
115
|
+
end
|
116
|
+
node_instance.security_groups
|
117
|
+
end
|
118
|
+
|
119
|
+
def node_instance_stopped?(node_instance)
|
120
|
+
!node_instance.ready?
|
121
|
+
end
|
122
|
+
|
123
|
+
def wait_for_task_completion(node_instance)
|
124
|
+
node_instance.wait_for { ready? }
|
125
|
+
end
|
126
|
+
|
127
|
+
def create_node_instance
|
128
|
+
Dopv::log.info("Node #{nodename}: Creating node instance.")
|
129
|
+
|
130
|
+
@node_creation_opts[:nics] = add_node_network_ports
|
131
|
+
@node_creation_opts[:user_data_encoded] = [cloud_config].pack('m')
|
132
|
+
|
133
|
+
Dopv::log.debug("Node #{nodename}: Spawning node instance.")
|
134
|
+
instance = compute_provider.servers.create(@node_creation_opts)
|
135
|
+
wait_for_task_completion(instance)
|
136
|
+
instance.reload
|
137
|
+
|
138
|
+
assign_security_groups(instance)
|
139
|
+
|
140
|
+
instance
|
141
|
+
end
|
142
|
+
|
143
|
+
def destroy_node_instance(node_instance, destroy_data_volumes=false)
|
144
|
+
remove_node_floating_ips(node_instance)
|
145
|
+
remove_node_network_ports(node_instance)
|
146
|
+
super(node_instance, destroy_data_volumes)
|
147
|
+
end
|
148
|
+
|
149
|
+
def start_node_instance(node_instance)
|
150
|
+
end
|
151
|
+
|
152
|
+
def stop_node_instance(node_instance)
|
153
|
+
super(node_instance)
|
154
|
+
node_instance.wait_for { !ready? }
|
155
|
+
end
|
156
|
+
|
157
|
+
def add_node_volume(node_instance, config)
|
158
|
+
volume = super(
|
159
|
+
compute_provider, {
|
160
|
+
:name => config.name,
|
161
|
+
:display_name => config.name,
|
162
|
+
:size => config.size.gibibytes.to_i,
|
163
|
+
:volume_type => config.pool,
|
164
|
+
:description => config.name
|
165
|
+
}
|
166
|
+
)
|
167
|
+
volume.wait_for { ready? }
|
168
|
+
attach_node_volume(node_instance, volume.reload)
|
169
|
+
volume.reload
|
170
|
+
end
|
171
|
+
|
172
|
+
def destroy_node_volume(node_instance, volume)
|
173
|
+
volume_instance = detach_node_volume(node_instance, volume)
|
174
|
+
volume_instance.destroy
|
175
|
+
node_instance.volumes.all({}).reload
|
176
|
+
end
|
177
|
+
|
178
|
+
def attach_node_volume(node_instance, volume)
|
179
|
+
volume_instance = node_instance.volumes.all({}).find { |v| v.id = volume.id }
|
180
|
+
node_instance.attach_volume(volume_instance.id, nil)
|
181
|
+
volume_instance.wait_for { volume_instance.status.downcase == "in-use" }
|
182
|
+
volume_instance
|
183
|
+
end
|
184
|
+
|
185
|
+
def detach_node_volume(node_instance, volume)
|
186
|
+
volume_instance = node_instance.volumes.all({}).find { |v| v.id = volume.id }
|
187
|
+
node_instance.detach_volume(volume_instance.id)
|
188
|
+
volume_instance.wait_for { volume_instance.status.downcase == "available" }
|
189
|
+
volume_instance
|
190
|
+
end
|
191
|
+
|
192
|
+
def record_node_data_volume(volume)
|
193
|
+
super(
|
194
|
+
:name => volume.name,
|
195
|
+
:id => volume.id,
|
196
|
+
:pool => volume.type == 'None' ? nil : volume.type,
|
197
|
+
:size => volume.size * 1073741824 # Returned in gibibytes
|
198
|
+
)
|
199
|
+
end
|
200
|
+
|
201
|
+
def fixed_ip(subnet_id, ip_address)
|
202
|
+
rval = { :subnet_id => subnet_id }
|
203
|
+
[:dhcp, :none].include?(ip_address) ? rval : rval.merge(:ip_address => ip_address)
|
204
|
+
end
|
205
|
+
|
206
|
+
def add_node_network_port(attrs)
|
207
|
+
::Dopv::log.debug("Node #{nodename}: Adding network port #{attrs[:name]}.")
|
208
|
+
network_provider.ports.create(attrs)
|
209
|
+
end
|
210
|
+
|
211
|
+
def add_node_network_ports
|
212
|
+
::Dopv::log.info("Node #{nodename}: Adding network ports.")
|
213
|
+
ports_config = {}
|
214
|
+
interfaces_config.each do |i|
|
215
|
+
s = subnet(i.network)
|
216
|
+
port_name = "#{nodename}_#{s.network_id}"
|
217
|
+
if ports_config.has_key?(port_name)
|
218
|
+
ports_config[port_name][:fixed_ips] << fixed_ip(s.id, i.ip)
|
219
|
+
else
|
220
|
+
ports_config[port_name] = {
|
221
|
+
:network_id => s.network_id,
|
222
|
+
:fixed_ips => [fixed_ip(s.id, i.ip)]
|
223
|
+
}
|
224
|
+
end
|
225
|
+
end
|
226
|
+
@network_ports = ports_config.map { |k,v| add_node_network_port(v.merge(:name => k)) }
|
227
|
+
@network_ports.collect { |p| {:net_id => p.network_id, :port_id => p.id} } # Net ID is required in Liberty++
|
228
|
+
end
|
229
|
+
|
230
|
+
def remove_node_network_ports(node_instance)
|
231
|
+
::Dopv::log.warn("Node #{nodename}: Removing network ports.")
|
232
|
+
@network_ports ||= network_provider.ports.select { |p| p.device_id == node_instance.id } rescue {}
|
233
|
+
@network_ports.each { |p| p.destroy rescue nil } # TODO: dangerous, rewrite
|
234
|
+
@network_ports = {}
|
235
|
+
end
|
236
|
+
|
237
|
+
def add_node_floating_ip(attrs)
|
238
|
+
::Dopv::log.debug("Node #{nodename}: Adding floating IP to #{attrs[:nicname]}.")
|
239
|
+
network_provider.floating_ips.create(attrs)
|
240
|
+
end
|
241
|
+
|
242
|
+
def add_node_floating_ips(node_instance)
|
243
|
+
::Dopv::log.info("Node #{nodename}: Adding floating IPs.")
|
244
|
+
@network_ports ||= network_provider.ports.select { |p| p.device_id == node_instance.id }
|
245
|
+
interfaces_config.each do |i|
|
246
|
+
if i.floating_network
|
247
|
+
floating_network = network(i.floating_network)
|
248
|
+
subnetwork = subnet(i.network)
|
249
|
+
port = @network_ports.find { |p| p.fixed_ips.find { |f| f["subnet_id"] == subnetwork.id } }
|
250
|
+
attrs = {
|
251
|
+
:floating_network_id => floating_network.id,
|
252
|
+
:port_id => port.id,
|
253
|
+
:fixed_ip_address => port.fixed_ips.first["ip_address"],
|
254
|
+
:nicname => i.name
|
255
|
+
}
|
256
|
+
add_node_floating_ip(attrs)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
alias_method :add_node_nics, :add_node_floating_ips
|
261
|
+
|
262
|
+
def remove_node_floating_ips(node_instance)
|
263
|
+
::Dopv::log.warn("Node #{nodename}: Removing floating IPs.")
|
264
|
+
if node_instance
|
265
|
+
floating_ips = network_provider.floating_ips.select do |f|
|
266
|
+
node_instance.floating_ip_addresses.include?(f.floating_ip_address)
|
267
|
+
end
|
268
|
+
floating_ips.each { |f| f.destroy rescue nil } # TODO: dangerous, rewrite
|
269
|
+
end
|
270
|
+
end
|
271
|
+
alias_method :remove_node_nics, :remove_node_floating_ips
|
272
|
+
|
273
|
+
def cloud_config
|
274
|
+
config = "#cloud-config\n" \
|
275
|
+
"hostname: #{hostname}\n" \
|
276
|
+
"fqdn: #{fqdn}\n" \
|
277
|
+
"manage_etc_hosts: True\n" \
|
278
|
+
"ssh_pwauth: True\n"
|
279
|
+
|
280
|
+
if root_password
|
281
|
+
config << \
|
282
|
+
"chpasswd:\n" \
|
283
|
+
" list: |\n" \
|
284
|
+
" root:#{root_password}\n" \
|
285
|
+
" expire: False\n"
|
286
|
+
end
|
287
|
+
|
288
|
+
unless root_ssh_pubkeys.empty?
|
289
|
+
config << \
|
290
|
+
"users:\n" \
|
291
|
+
" - name: root\n" \
|
292
|
+
" ssh_authorized_keys:\n"
|
293
|
+
root_ssh_pubkeys.each { |k| config << " - #{k}\n" }
|
294
|
+
end
|
295
|
+
|
296
|
+
config <<
|
297
|
+
"runcmd:\n" \
|
298
|
+
" - service network restart\n"
|
299
|
+
|
300
|
+
config
|
301
|
+
end
|
302
|
+
|
303
|
+
def get_node_ip_addresses(node_instance)
|
304
|
+
(node_instance.ip_addresses + [node_instance.floating_ip_address]).flatten.uniq.compact
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
require 'fog'
|
2
|
+
require 'uri'
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
module Dopv
|
6
|
+
module Infrastructure
|
7
|
+
class Ovirt < Base
|
8
|
+
def initialize(plan, data_disks_db)
|
9
|
+
super(plan, data_disks_db)
|
10
|
+
|
11
|
+
@compute_connection_opts = {
|
12
|
+
:provider => 'ovirt',
|
13
|
+
:ovirt_username => provider_username,
|
14
|
+
:ovirt_password => provider_password,
|
15
|
+
:ovirt_url => provider_url,
|
16
|
+
:ovirt_ca_cert_file => provider_ca_cert_file
|
17
|
+
}
|
18
|
+
|
19
|
+
@node_creation_opts = {
|
20
|
+
:name => nodename,
|
21
|
+
:template => template.id,
|
22
|
+
:cores => cores,
|
23
|
+
:memory => memory.bytes,
|
24
|
+
:storage => storage.bytes,
|
25
|
+
:cluster => cluster.id,
|
26
|
+
:ha => keep_ha?,
|
27
|
+
:clone => full_clone?,
|
28
|
+
:storagedomain_name => infrastructure_properties.default_pool
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def compute_provider
|
35
|
+
unless @compute_provider
|
36
|
+
super
|
37
|
+
::Dopv::log.debug("Node #{nodename}: Recreating client with proper datacenter.")
|
38
|
+
@compute_connection_opts[:ovirt_datacenter] = datacenter[:id]
|
39
|
+
@compute_provider = ::Fog::Compute.new(@compute_connection_opts)
|
40
|
+
end
|
41
|
+
@compute_provider
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_node_instance
|
45
|
+
super({:without_details => true})
|
46
|
+
end
|
47
|
+
|
48
|
+
def wait_for_task_completion(node_instance)
|
49
|
+
node_instance.wait_for { !locked? }
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_node_instance
|
53
|
+
node_instance = super
|
54
|
+
|
55
|
+
# For each disk, set up wipe after delete flag
|
56
|
+
node_instance.volumes.each do |v|
|
57
|
+
::Dopv::log.debug("Node #{nodename}: Setting wipe after delete for disk #{v.alias}.")
|
58
|
+
update_node_volume(node_instance, v, {:wipe_after_delete => true})
|
59
|
+
end
|
60
|
+
|
61
|
+
node_instance
|
62
|
+
end
|
63
|
+
|
64
|
+
def customize_node_instance(node_instance)
|
65
|
+
::Dopv::log.info("Node #{nodename}: Customizing node.")
|
66
|
+
customization_opts = {
|
67
|
+
:hostname => fqdn,
|
68
|
+
:dns => dns.name_servers,
|
69
|
+
:domain => dns.search_domains,
|
70
|
+
:user => 'root',
|
71
|
+
:password => root_password,
|
72
|
+
:ssh_authorized_keys => root_ssh_pubkeys
|
73
|
+
}
|
74
|
+
|
75
|
+
customization_opts[:nicsdef] = interfaces_config.collect do |i|
|
76
|
+
nic = {}
|
77
|
+
nic[:nicname] = i.name
|
78
|
+
nic[:on_boot] = 'true'
|
79
|
+
nic[:boot_protocol] = case i.ip
|
80
|
+
when :dhcp
|
81
|
+
'DHCP'
|
82
|
+
when :none
|
83
|
+
'NONE'
|
84
|
+
else
|
85
|
+
'STATIC'
|
86
|
+
end
|
87
|
+
unless [:dhcp, :none].include?(i.ip)
|
88
|
+
nic[:ip] = i.ip
|
89
|
+
nic[:netmask] = i.netmask
|
90
|
+
nic[:gateway] = i.gateway if i.set_gateway?
|
91
|
+
end
|
92
|
+
nic
|
93
|
+
end
|
94
|
+
|
95
|
+
customization_opts
|
96
|
+
end
|
97
|
+
|
98
|
+
def start_node_instance(node_instance)
|
99
|
+
customization_opts = super(node_instance)
|
100
|
+
node_instance.service.vm_start_with_cloudinit(
|
101
|
+
:id => node_instance.id,
|
102
|
+
:user_data => customization_opts
|
103
|
+
)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Redefine until regexp in Fog::Compute::Ovirt::Server#stopped? is fixed
|
107
|
+
def stop_node_instance(node_instance)
|
108
|
+
super
|
109
|
+
node_instance.wait_for { status.downcase == 'down' }
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_node_nic(node_instance, attrs)
|
113
|
+
nic = node_instance.add_interface(attrs)
|
114
|
+
node_instance.interfaces.reload
|
115
|
+
nic
|
116
|
+
end
|
117
|
+
|
118
|
+
def update_node_nic(node_instance, nic, attrs)
|
119
|
+
node_instance.update_interface(attrs.merge({:id => nic.id}))
|
120
|
+
node_instance.interfaces.reload
|
121
|
+
end
|
122
|
+
|
123
|
+
def add_node_nics(node_instance)
|
124
|
+
::Dopv::log.info("Node #{nodename}: Trying to add interfaces.")
|
125
|
+
|
126
|
+
# Remove all interfaces defined by the template
|
127
|
+
remove_node_nics(node_instance) { |n, i| n.destroy_interface(:id => i.id) }
|
128
|
+
|
129
|
+
# fetch first network for our reservation dance
|
130
|
+
first_network = cluster.networks.first.name
|
131
|
+
# Reserve MAC addresses
|
132
|
+
(1..interfaces_config.size).each do |i|
|
133
|
+
name = "tmp#{i}"
|
134
|
+
::Dopv::log.debug("Node #{nodename}: Creating interface #{name}.")
|
135
|
+
attrs = {
|
136
|
+
:name => name,
|
137
|
+
:network_name => first_network,
|
138
|
+
:plugged => true,
|
139
|
+
:linked => true
|
140
|
+
}
|
141
|
+
add_node_nic(node_instance, attrs)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Rearrange interfaces by their MAC addresses and assign them into
|
145
|
+
# appropriate networks
|
146
|
+
ic = interfaces_config.reverse
|
147
|
+
node_instance.interfaces.sort_by do |n| n.mac
|
148
|
+
i = ic.pop
|
149
|
+
::Dopv::log.debug("Node #{nodename}: Configuring interface #{n.name} (#{n.mac}) as #{i.name} in #{i.network}.")
|
150
|
+
attrs = {
|
151
|
+
:name => i.name,
|
152
|
+
:network_name => i.network,
|
153
|
+
}
|
154
|
+
update_node_nic(node_instance, n, attrs)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def add_node_affinity(node_instance, name)
|
159
|
+
affinity_group = compute_provider.affinity_groups.find { |g| g.name == name }
|
160
|
+
raise ProviderError, "No such affinity group #{name}" unless affinity_group
|
161
|
+
::Dopv::log.info("Node #{nodename}: Adding node to affinity group #{name}.")
|
162
|
+
node_instance.add_to_affinity_group(:id => affinity_group.id)
|
163
|
+
end
|
164
|
+
|
165
|
+
def add_node_volume(node_instance, config)
|
166
|
+
storage_domain = compute_provider.storage_domains.find { |d| d.name == config.pool }
|
167
|
+
raise ProviderError, "No such storage domain #{storage_domain_name}" unless storage_domain
|
168
|
+
|
169
|
+
node_instance.add_volume(
|
170
|
+
{
|
171
|
+
:alias => config.name,
|
172
|
+
:size => config.size.bytes,
|
173
|
+
:bootable => 'false',
|
174
|
+
:wipe_after_delete => 'true',
|
175
|
+
:storage_domain => storage_domain.id
|
176
|
+
}.tap { |h| (h[:format] = 'raw'; h[:sparse] = 'false') unless config.thin? }
|
177
|
+
)
|
178
|
+
wait_for_task_completion(node_instance)
|
179
|
+
node_instance.volumes.find { |v| v.alias == config.name } # TODO: Rewrite with volume.reload if possible
|
180
|
+
end
|
181
|
+
|
182
|
+
def destroy_node_volume(node_instance, volume)
|
183
|
+
node_instance.destroy_volume(:id => volume.id)
|
184
|
+
wait_for_task_completion(node_instance)
|
185
|
+
node_instance.volumes.reload
|
186
|
+
end
|
187
|
+
|
188
|
+
def attach_node_volume(node_instance, volume)
|
189
|
+
node_instance.attach_volume(:id => volume.id)
|
190
|
+
wait_for_task_completion(node_instance)
|
191
|
+
node_instance.volumes.reload
|
192
|
+
end
|
193
|
+
|
194
|
+
def detach_node_volume(node_instance, volume)
|
195
|
+
node_instance.detach_volume(:id => volume.id)
|
196
|
+
wait_for_task_completion(node_instance)
|
197
|
+
node_instance.volumes.reload
|
198
|
+
end
|
199
|
+
|
200
|
+
def record_node_data_volume(volume)
|
201
|
+
super(
|
202
|
+
:name => volume.alias,
|
203
|
+
:id => volume.id,
|
204
|
+
:pool => volume.storage_domain,
|
205
|
+
:size => volume.size
|
206
|
+
)
|
207
|
+
end
|
208
|
+
|
209
|
+
def provider_ca_cert_file
|
210
|
+
uri = infrastructure.endpoint
|
211
|
+
local_ca_file = "#{TMP}/#{uri.host}_#{uri.port}_ca.crt"
|
212
|
+
remote_ca_file = "#{uri.scheme}://#{uri.host}:#{uri.port}/ca.crt"
|
213
|
+
unless File.exists?(local_ca_file)
|
214
|
+
begin
|
215
|
+
open(remote_ca_file, :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE) do |remote_ca|
|
216
|
+
local_ca = open(local_ca_file, 'w')
|
217
|
+
local_ca.write(remote_ca.read)
|
218
|
+
local_ca.close
|
219
|
+
end
|
220
|
+
rescue
|
221
|
+
raise ProviderError, "Cannot download CA certificate from #{provider_url}"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
local_ca_file
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|