chef-provisioning-oneview 1.2.1 → 1.3.0
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 -65
- data/chef-provisioning-oneview.gemspec +39 -0
- data/lib/chef/provisioning/create_machine.rb +43 -46
- data/lib/chef/provisioning/customize_machine.rb +50 -48
- data/lib/chef/provisioning/helpers.rb +18 -0
- data/lib/chef/provisioning/icsp/api_v104.rb +3 -2
- data/lib/chef/provisioning/icsp/icsp_helper.rb +288 -0
- data/lib/chef/provisioning/icsp/rest.rb +50 -0
- data/lib/chef/provisioning/oneview/oneview_helper.rb +53 -0
- data/lib/chef/provisioning/oneview/san_storage.rb +69 -69
- data/lib/chef/provisioning/oneview_driver.rb +124 -105
- data/lib/chef/provisioning/version.rb +1 -1
- metadata +23 -61
- data/Rakefile +0 -19
- data/lib/chef/provisioning/icsp/icsp_api.rb +0 -284
- data/lib/chef/provisioning/oneview/oneview_api.rb +0 -186
- data/lib/chef/provisioning/oneview/v1.2/api.rb +0 -3
- data/lib/chef/provisioning/oneview/v2.0/api.rb +0 -3
- data/lib/chef/provisioning/rest.rb +0 -52
- data/spec/shared_context.rb +0 -78
- data/spec/spec_helper.rb +0 -23
- data/spec/support/fake_action_handler.rb +0 -6
- data/spec/support/fake_icsp.rb +0 -73
- data/spec/support/fake_machine_spec.rb +0 -18
- data/spec/support/fake_oneview.rb +0 -148
- data/spec/support/fixtures/icsp/v102/error_404.json +0 -14
- data/spec/support/fixtures/icsp/v102/login.json +0 -5
- data/spec/support/fixtures/icsp/v102/os-deployment-build-plans.json +0 -99
- data/spec/support/fixtures/icsp/v102/os-deployment-servers.json +0 -179
- data/spec/support/fixtures/icsp/v102/os-deployment-servers_1670001.json +0 -83
- data/spec/support/fixtures/icsp/v102/os-deployment-servers_fakesn.json +0 -9
- data/spec/support/fixtures/icsp/v102/server_by_sn_VCGE9KB041.json +0 -45
- data/spec/support/fixtures/icsp/v102/server_by_sn_empty.json +0 -16
- data/spec/support/fixtures/icsp/v102/version.json +0 -4
- data/spec/support/fixtures/oneview/v120/error_404.json +0 -14
- data/spec/support/fixtures/oneview/v120/login.json +0 -5
- data/spec/support/fixtures/oneview/v120/server-hardware.json +0 -1476
- data/spec/support/fixtures/oneview/v120/server-hardware_Template-WebServer.json +0 -468
- data/spec/support/fixtures/oneview/v120/server-hardware_specific.json +0 -151
- data/spec/support/fixtures/oneview/v120/server-profiles.json +0 -369
- data/spec/support/fixtures/oneview/v120/server-profiles_invalid_filter.json +0 -14
- data/spec/support/fixtures/oneview/v120/server-profiles_name_Template-WebServer.json +0 -133
- data/spec/support/fixtures/oneview/v120/server-profiles_name_Template-WebServerWithSAN.json +0 -200
- data/spec/support/fixtures/oneview/v120/server-profiles_name_chef-web01.json +0 -133
- data/spec/support/fixtures/oneview/v120/server-profiles_name_chef-web03.json +0 -133
- data/spec/support/fixtures/oneview/v120/server-profiles_name_empty.json +0 -15
- data/spec/support/fixtures/oneview/v120/server-profiles_sn_VCGE9KB041.json +0 -133
- data/spec/support/fixtures/oneview/v120/server-profiles_sn_VCGE9KB042.json +0 -206
- data/spec/support/fixtures/oneview/v120/server-profiles_sn_empty.json +0 -15
- data/spec/support/fixtures/oneview/v120/storage-volumes_1B5D3CA2-6C5B-41C2-8B97-1821F1883F22.json +0 -26
- data/spec/support/fixtures/oneview/v120/tasks_fake_active.json +0 -5
- data/spec/support/fixtures/oneview/v120/tasks_fake_complete.json +0 -5
- data/spec/support/fixtures/oneview/v120/version.json +0 -4
- data/spec/support/fixtures/oneview/v200/server-profile-templates_WebServerTemplate.json +0 -109
- data/spec/support/fixtures/oneview/v200/server-profile-templates_WebServerTemplateWithSAN.json +0 -144
- data/spec/support/fixtures/oneview/v200/server-profile-templates_invalid.json +0 -16
- data/spec/support/fixtures/oneview/v200/server-profile-templates_new-profile_WebServerTemplate.json +0 -125
- data/spec/support/fixtures/oneview/v200/server-profile-templates_new-profile_WebServerTemplateWithSAN.json +0 -178
- data/spec/support/fixtures/oneview/v200/version.json +0 -4
- data/spec/unit/create_machine_spec.rb +0 -78
- data/spec/unit/destroy_spec.rb +0 -26
- data/spec/unit/icsp_nic_teams_spec.rb +0 -38
- data/spec/unit/icsp_search_spec.rb +0 -25
- data/spec/unit/oneview_driver_spec.rb +0 -79
- data/spec/unit/oneview_login_spec.rb +0 -17
- data/spec/unit/oneview_power_spec.rb +0 -51
- data/spec/unit/oneview_san_spec.rb +0 -86
- data/spec/unit/oneview_search_spec.rb +0 -63
- data/spec/unit/rest_api_spec.rb +0 -115
@@ -0,0 +1,53 @@
|
|
1
|
+
module OneviewChefProvisioningDriver
|
2
|
+
# Helpers for OneView actions
|
3
|
+
module OneViewHelper
|
4
|
+
# Create new Profile from template or server profile
|
5
|
+
# @return [OneviewSDK::ServerProfile] server profile
|
6
|
+
def profile_from_template(template_name, profile_name)
|
7
|
+
raise 'Template name missing! Please set machine_options[:driver_options][:server_template]' unless template_name
|
8
|
+
if @ov.api_version >= 200
|
9
|
+
# Look for Server Profile Template (OneView 2.0 or higher)
|
10
|
+
template = OneviewSDK::ServerProfileTemplate.find_by(@ov, name: template_name).first
|
11
|
+
return template.new_profile(profile_name) if template
|
12
|
+
end
|
13
|
+
|
14
|
+
# Look for Server Profile as second option
|
15
|
+
profile = OneviewSDK::ServerProfile.find_by(@ov, name: template_name).first
|
16
|
+
raise "Template '#{template_name}' not found! Please match the template name with one that exists on OneView." unless profile
|
17
|
+
profile['name'] = profile_name
|
18
|
+
|
19
|
+
# Remove unwanted fields
|
20
|
+
%w(uri serialNumber uuid taskUri enclosureBay enclosureUri).each { |key| profile.data.delete(key) }
|
21
|
+
profile['connections'].each do |c|
|
22
|
+
%w(wwnn wwpn mac deploymentStatus interconnectUri wwpnType macType).each { |key| c[key] = nil }
|
23
|
+
end
|
24
|
+
profile
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get an available hardware for a template. If a specific location is requested, find it
|
28
|
+
# @return [OneviewSDK::ServerHardware]
|
29
|
+
def available_hardware_for_profile(profile, location = nil)
|
30
|
+
Chef::Log.debug "Specific hardware requested: #{location}" if location
|
31
|
+
hw_list = profile.get_available_hardware
|
32
|
+
raise 'Error! No available blades that are compatible with the server template!' if hw_list.empty?
|
33
|
+
if location
|
34
|
+
chosen_blade = hw_list.find { |h| h['name'] == location }
|
35
|
+
return chosen_blade if chosen_blade
|
36
|
+
raise "Specified hardware '#{location}' doesn't exist or doesn't match the given template"
|
37
|
+
end
|
38
|
+
hw_list.first # If no location is specified, return the first matching HW
|
39
|
+
end
|
40
|
+
|
41
|
+
# Wait for the profile to finish being applied
|
42
|
+
# @return [TrueClass, FalseClass]
|
43
|
+
def wait_for_profile(action_handler, machine_name, profile)
|
44
|
+
return true if profile['state'] == 'Normal'
|
45
|
+
action_handler.perform_action "Apply profile '#{profile['name']}' for machine '#{machine_name}'" do
|
46
|
+
action_handler.report_progress "INFO: Applying profile '#{profile['name']}' for machine '#{machine_name}'"
|
47
|
+
@ov.wait_for(profile['taskUri'])
|
48
|
+
end
|
49
|
+
profile.refresh
|
50
|
+
raise "Server profile state '#{profile['state']}' not 'Normal'" unless profile['state'] == 'Normal'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -1,91 +1,91 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
module OneviewChefProvisioningDriver
|
2
|
+
# Methods for configuring SAN storage on OneView
|
3
|
+
module OneViewSanStorage
|
4
|
+
def fill_volume_details(v)
|
5
|
+
response = @ov.rest_get(v['volumeUri'])
|
6
|
+
details = @ov.response_handler(response)
|
7
|
+
v['volumeName'] = details['name']
|
8
|
+
v['permanent'] = details['isPermanent']
|
9
|
+
v['volumeShareable'] = details['shareable']
|
10
|
+
v['volumeProvisionType'] = details['provisionType']
|
11
|
+
v['volumeProvisionedCapacityBytes'] = details['provisionedCapacity']
|
12
|
+
v['volumeDescription'] = details['description']
|
13
|
+
v
|
14
|
+
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
# Prepare profile for SAN storage
|
17
|
+
def update_san_info(machine_name, profile)
|
18
|
+
san_storage = profile['sanStorage']
|
19
|
+
return profile unless san_storage && !san_storage['volumeAttachments'].empty?
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
# Sanitize old SAN entries and fill in details
|
22
|
+
boot_vols = []
|
23
|
+
san_storage['volumeAttachments'].each do |v|
|
24
|
+
fill_volume_details(v) unless profile['serverProfileTemplateUri']
|
25
|
+
raise "#{machine_name}: Should know if volume is sharable:\n#{v}" unless v.key?('volumeShareable')
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
# Match boot disks by name
|
28
|
+
boot_vols.push(v['volumeName']) if v['volumeName'] =~ /^boot/i
|
29
|
+
v['volumeName'] += " #{profile['name']}" unless v['volumeShareable'] # Append profile name to volume name
|
28
30
|
|
29
|
-
|
31
|
+
next if profile['serverProfileTemplateUri'] # Only needed when coppied from profile
|
30
32
|
v['state'] = nil
|
31
33
|
v['status'] = nil
|
32
34
|
v['storagePaths'].each { |s| s['status'] = nil }
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
36
|
+
next if v['volumeShareable']
|
37
|
+
# It is private in the profile, so we will clone it
|
38
|
+
v['volumeUri'] = nil
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
40
|
+
# Assumes all cloned volumes are non-permanet. Might want some global config to control this
|
41
|
+
v['permanent'] = false
|
42
|
+
v['lun'] = nil if v['lunType'].casecmp('auto') == 0
|
42
43
|
end
|
44
|
+
raise "#{machine_name}: There should only be 1 SAN boot volume. Boot volumes: #{boot_vols}" if boot_vols.size > 1
|
45
|
+
profile
|
43
46
|
end
|
44
|
-
raise "#{machine_spec.name}: There should only be 1 SAN boot volume. Boot volumes: #{boot_vols}" if boot_vols.size > 1
|
45
|
-
profile
|
46
|
-
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
# Make sure connections for SAN boot volumes are configured to boot from the correct SAN volume
|
49
|
+
# @return false if no connections are available to configure
|
50
|
+
def enable_boot_from_san(action_handler, machine_name, profile)
|
51
|
+
return false if profile['connections'].nil? || profile['connections'].empty?
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
53
|
+
# If there is a san volume we might need to update boot connections
|
54
|
+
update_needed = false
|
55
|
+
profile['sanStorage']['volumeAttachments'].each do |v|
|
56
|
+
response = @ov.rest_get(v['volumeUri'])
|
57
|
+
vol_details = @ov.response_handler(response)
|
58
|
+
next unless vol_details['name'] =~ /^boot/i
|
59
|
+
# Find the enabled path(s), get target wwpn, and then update connection, setting boot targets
|
60
|
+
v['storagePaths'].each do |s|
|
61
|
+
next if !s['isEnabled'] || s['storageTargets'].nil? || s['storageTargets'].empty?
|
62
|
+
connection = profile['connections'].find { |c| c['id'] == s['connectionId'] }
|
63
|
+
raise "#{machine_name}: Connection #{s['connectionId']} not found! Check SAN settings" unless connection
|
64
|
+
if connection['boot'].nil? || connection['boot']['priority'] == 'NotBootable'
|
65
|
+
msg = "#{machine_name}: Connection #{s['connectionId']} is labeled for boot, but the connection is not marked as bootable."
|
66
|
+
raise "#{msg} Set the connection boot target to Primary or Secondary"
|
67
|
+
end
|
68
|
+
target = {}
|
69
|
+
target['arrayWwpn'] = s['storageTargets'].first.delete(':')
|
70
|
+
target['lun'] = v['lun']
|
71
|
+
unchanged = connection['boot']['targets'] && connection['boot']['targets'].first &&
|
72
|
+
connection['boot']['targets'].first['arrayWwpn'] == target['arrayWwpn'] &&
|
73
|
+
connection['boot']['targets'].first['lun'] == target['lun']
|
74
|
+
next if unchanged
|
72
75
|
connection['boot']['targets'] = [target]
|
73
76
|
update_needed = true
|
74
77
|
end
|
75
78
|
end
|
76
|
-
end
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
raise "Error enabling SAN-bootable connections on #{machine_spec.name}. Response: #{task}" unless task == true
|
80
|
+
if update_needed
|
81
|
+
action_handler.perform_action "Enable SAN-bootable connections for #{machine_name}" do
|
82
|
+
action_handler.report_progress "INFO: Enabling SAN-bootable connections for #{machine_name}"
|
83
|
+
profile.get_server_hardware.power_off
|
84
|
+
profile.update
|
85
|
+
end
|
86
|
+
profile.refresh
|
86
87
|
end
|
87
|
-
profile
|
88
|
+
profile # Return profile
|
88
89
|
end
|
89
|
-
profile # Return profile
|
90
90
|
end
|
91
91
|
end
|
@@ -6,90 +6,91 @@ require 'chef/provisioning/driver'
|
|
6
6
|
require 'chef/provisioning/transport/ssh'
|
7
7
|
require 'chef/provisioning/machine/unix_machine'
|
8
8
|
require 'json'
|
9
|
+
require 'oneview-sdk'
|
9
10
|
require_relative 'driver_init/oneview'
|
10
11
|
require_relative 'version'
|
11
|
-
require_relative '
|
12
|
-
require_relative 'create_machine'
|
13
|
-
require_relative 'customize_machine'
|
14
|
-
require_relative 'oneview/oneview_api'
|
15
|
-
require_relative 'icsp/icsp_api'
|
12
|
+
require_relative 'helpers'
|
16
13
|
|
17
14
|
module Chef::Provisioning
|
15
|
+
# Provisioning driver for HPE OneView
|
18
16
|
class OneViewDriver < Chef::Provisioning::Driver
|
19
|
-
include
|
20
|
-
include CustomizeMachine
|
21
|
-
include RestAPI
|
22
|
-
include OneViewAPI
|
23
|
-
include ICspAPI
|
24
|
-
|
17
|
+
include OneviewChefProvisioningDriver::Helpers
|
25
18
|
|
26
19
|
def self.canonicalize_url(url, config)
|
27
20
|
_scheme, oneview_url = url.split(':', 2)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
raise 'Must set the
|
32
|
-
|
21
|
+
oneview_url ||= config[:driver_options][:oneview][:url] rescue nil
|
22
|
+
oneview_url ||= config[:knife][:oneview_url] rescue nil
|
23
|
+
oneview_url ||= ENV['ONEVIEWSDK_URL']
|
24
|
+
raise 'Must set the oneview driver url! See docs for more info' if oneview_url.nil? || oneview_url.empty?
|
25
|
+
"oneview:#{oneview_url}"
|
33
26
|
end
|
34
27
|
|
35
|
-
def self.from_url(
|
36
|
-
OneViewDriver.new(
|
28
|
+
def self.from_url(url, config)
|
29
|
+
OneViewDriver.new(url, config)
|
37
30
|
end
|
38
31
|
|
39
|
-
def initialize(
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@
|
32
|
+
def initialize(url, config)
|
33
|
+
_scheme, oneview_url = url.split(':', 2)
|
34
|
+
super(url, config)
|
35
|
+
|
36
|
+
ov_config = config[:driver_options][:oneview] || {} rescue {}
|
37
|
+
ov_config = Hash[ov_config.map { |k, v| [k.to_sym, v] }] # Convert string keys to symbols
|
38
|
+
|
39
|
+
ov_config[:url] = oneview_url
|
40
|
+
ov_config[:user] ||= config[:knife][:oneview_username] || ENV['ONEVIEWSDK_USER']
|
41
|
+
ov_config[:password] ||= config[:knife][:oneview_password] || ENV['ONEVIEWSDK_PASSWORD']
|
42
|
+
ov_config[:token] ||= config[:knife][:oneview_token] || ENV['ONEVIEWSDK_TOKEN']
|
43
|
+
ov_config[:ssl_enabled] = false if ov_config[:ssl_enabled] == false || (ov_config[:ssl_enabled].nil? && config[:knife][:oneview_ignore_ssl])
|
44
|
+
ov_config[:timeout] ||= config[:knife][:oneview_timeout] if config[:knife][:oneview_timeout]
|
45
|
+
ov_config[:print_wait_dots] = true if ov_config[:print_wait_dots].nil?
|
46
|
+
ov_config[:logger] = Chef::Log
|
47
|
+
@ov = OneviewSDK::Client.new(ov_config) # OneView client object
|
48
|
+
|
49
|
+
icsp_config = config[:driver_options][:icsp] || {} rescue {}
|
50
|
+
|
51
|
+
@icsp_base_url = icsp_config[:url] || config[:knife][:icsp_url]
|
52
|
+
@icsp_username = icsp_config[:user] || config[:knife][:icsp_username]
|
53
|
+
@icsp_password = icsp_config[:password] || config[:knife][:icsp_password]
|
54
|
+
@icsp_disable_ssl = false
|
55
|
+
@icsp_disable_ssl = true if icsp_config[:ssl_enabled] == false || config[:knife][:icsp_ignore_ssl] == true
|
59
56
|
@icsp_api_version = 102 # Use this version for all calls that don't override it
|
57
|
+
@icsp_timeout = icsp_config[:timeout] || config[:knife][:icsp_timeout]
|
60
58
|
|
61
|
-
Chef::Log.warn '
|
62
|
-
Chef::Log.warn '
|
63
|
-
Chef::Log.warn '
|
59
|
+
Chef::Log.warn 'ICSP url not set! ICSP will be ignored' if @icsp_base_url.nil?
|
60
|
+
Chef::Log.warn 'ICSP user not set! ICSP will be ignored' if @icsp_username.nil?
|
61
|
+
Chef::Log.warn 'ICSP password not set! ICSP will be ignored' if @icsp_password.nil?
|
64
62
|
|
65
63
|
@icsp_ignore = @icsp_base_url.nil? || @icsp_username.nil? || @icsp_password.nil?
|
66
64
|
# If the config is not specified, skip ICSP
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
65
|
+
return if @icsp_ignore
|
66
|
+
Chef::Log.debug("Logging into ICSP at #{@icsp_base_url}")
|
67
|
+
@current_icsp_api_version = get_icsp_api_version
|
68
|
+
@icsp_key = login_to_icsp
|
72
69
|
end
|
73
70
|
|
74
71
|
|
75
72
|
def allocate_machine(action_handler, machine_spec, machine_options)
|
76
|
-
|
73
|
+
raise 'Machine definition missing :driver_options parameter!' unless machine_options[:driver_options]
|
77
74
|
if machine_spec.reference
|
78
|
-
|
79
|
-
|
80
|
-
machine_spec.reference = nil
|
81
|
-
else # Update reference data
|
75
|
+
profile = OneviewSDK::ServerProfile.find_by(@ov, serialNumber: machine_spec.reference['serial_number']).first
|
76
|
+
if profile # Update reference data
|
82
77
|
machine_spec.reference['driver_url'] = driver_url
|
83
78
|
machine_spec.reference['driver_version'] = ONEVIEW_DRIVER_VERSION
|
79
|
+
# TODO: Update profile if differs from Chef and/or Template config
|
80
|
+
machine_spec.reference['profile_name'] = profile['name']
|
81
|
+
else # It doesn't really exist
|
82
|
+
action_handler.report_progress "Machine #{machine_spec.name} does not really exist. Recreating ..."
|
83
|
+
machine_spec.reference = nil
|
84
84
|
end
|
85
85
|
end
|
86
|
-
|
87
|
-
action_handler.perform_action "
|
88
|
-
profile = create_machine(action_handler, machine_spec, machine_options)
|
86
|
+
unless machine_spec.reference
|
87
|
+
action_handler.perform_action "Allocate server #{machine_spec.name}" do
|
88
|
+
profile = create_machine(action_handler, machine_spec.name, machine_options)
|
89
89
|
machine_spec.reference = {
|
90
90
|
'driver_url' => driver_url,
|
91
91
|
'driver_version' => ONEVIEW_DRIVER_VERSION,
|
92
|
-
'serial_number' => profile['serialNumber']
|
92
|
+
'serial_number' => profile['serialNumber'],
|
93
|
+
'profile_name' => profile['name']
|
93
94
|
}
|
94
95
|
end
|
95
96
|
end
|
@@ -102,37 +103,22 @@ module Chef::Provisioning
|
|
102
103
|
end
|
103
104
|
end
|
104
105
|
|
106
|
+
|
105
107
|
def ready_machine(action_handler, machine_spec, machine_options)
|
106
|
-
profile =
|
108
|
+
profile = OneviewSDK::ServerProfile.find_by(@ov, serialNumber: machine_spec.reference['serial_number']).first
|
107
109
|
raise "Failed to retrieve Server Profile for #{machine_spec.name}. Serial Number used to search: #{machine_spec.reference['serial_number']}" unless profile
|
110
|
+
customize_machine(action_handler, machine_spec, machine_options, profile)
|
108
111
|
if @icsp_ignore == true
|
109
|
-
|
110
|
-
Chef::Log.warn('Action converge action being used, without an ICSP configuration')
|
112
|
+
Chef::Log.warn("Skipping ICSP configuration for machine '#{machine_spec.name}'")
|
111
113
|
Machine::BasicMachine.new(machine_spec, OneViewNilTransport.new, OneViewNilConvergence.new)
|
112
|
-
else
|
113
|
-
|
114
|
-
customize_machine(action_handler, machine_spec, machine_options, profile)
|
115
|
-
# This is a provisining function and handles installing a chef-client
|
116
|
-
machine_for(machine_spec, machine_options) # Return the Machine object
|
114
|
+
else # Return a machine object that Chef can connect to (to install chef-client)
|
115
|
+
machine_for(machine_spec, machine_options)
|
117
116
|
end
|
118
117
|
end
|
119
118
|
|
120
119
|
|
121
120
|
def machine_for(machine_spec, machine_options)
|
122
|
-
bootstrap_ip_address = machine_options
|
123
|
-
unless bootstrap_ip_address
|
124
|
-
id, connection = machine_options[:driver_options][:connections].find { |_id, c| c[:bootstrap] == true }
|
125
|
-
raise 'Must specify a connection to use to bootstrap!' unless id && connection
|
126
|
-
bootstrap_ip_address = connection[:ip4Address] # For static IPs
|
127
|
-
unless bootstrap_ip_address # Look for dhcp address given to this connection
|
128
|
-
profile = get_oneview_profile_by_sn(machine_spec.reference['serial_number'])
|
129
|
-
my_server = get_icsp_server_by_sn(machine_spec.reference['serial_number'])
|
130
|
-
mac = profile['connections'].find {|x| x['id'] == id}['mac']
|
131
|
-
interface = my_server['interfaces'].find { |i| i['macAddr'] == mac }
|
132
|
-
bootstrap_ip_address = interface['ipv4Addr'] || interface['ipv6Addr']
|
133
|
-
end
|
134
|
-
bootstrap_ip_address ||= my_server['hostName'] # Fall back on hostName
|
135
|
-
end
|
121
|
+
bootstrap_ip_address = ip_from_machine(machine_spec, machine_options)
|
136
122
|
raise 'Server IP address not specified and could not be retrieved!' unless bootstrap_ip_address
|
137
123
|
username = machine_options[:transport_options][:user] || 'root' rescue 'root'
|
138
124
|
default_ssh_options = {
|
@@ -153,39 +139,46 @@ module Chef::Provisioning
|
|
153
139
|
Chef::Provisioning::Machine::UnixMachine.new(machine_spec, transport, convergence_strategy)
|
154
140
|
end
|
155
141
|
|
156
|
-
def stop_machine(
|
157
|
-
|
142
|
+
def stop_machine(_action_handler, machine_spec, _machine_options)
|
143
|
+
return unless machine_spec.reference
|
144
|
+
profile = OneviewSDK::ServerProfile.find_by(@ov, serialNumber: machine_spec.reference['serial_number']).first
|
145
|
+
profile.get_server_hardware.power_off
|
158
146
|
end
|
159
147
|
|
160
148
|
|
161
|
-
def destroy_machine(action_handler, machine_spec,
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
149
|
+
def destroy_machine(action_handler, machine_spec, machine_options)
|
150
|
+
return unless machine_spec.reference
|
151
|
+
profile = OneviewSDK::ServerProfile.find_by(@ov, serialNumber: machine_spec.reference['serial_number']).first
|
152
|
+
if profile
|
153
|
+
profile.get_server_hardware.power_off
|
154
|
+
action_handler.perform_action "Delete server profile #{machine_spec.name}" do
|
155
|
+
action_handler.report_progress "INFO: Deleting server profile #{machine_spec.name}"
|
156
|
+
profile.delete
|
157
|
+
end
|
158
|
+
else
|
159
|
+
action_handler.report_progress "INFO: #{machine_spec.name} is already deleted."
|
160
|
+
end
|
161
|
+
destroy_icsp_server(action_handler, machine_spec) unless @icsp_ignore # Delete os deployment server from ICSP
|
162
|
+
|
163
|
+
name = machine_spec.name # Save for next steps
|
164
|
+
|
165
|
+
# Remove entry from known_hosts file(s)
|
166
|
+
ip_address = ip_from_machine(machine_spec, machine_options)
|
167
|
+
return unless ip_address
|
168
|
+
action_handler.perform_action "Delete entries for #{name} (#{ip_address}) from known_hosts file(s)" do
|
169
|
+
files = [File.expand_path('~/.ssh/known_hosts'), File.expand_path('/etc/ssh/known_hosts')]
|
170
|
+
files.each do |f|
|
171
|
+
next unless File.exist?(f)
|
172
|
+
begin
|
173
|
+
text = File.read(f)
|
174
|
+
text.gsub!(/#{ip_address} ssh-rsa.*(\n|\r\n)/, '')
|
175
|
+
File.open(f, 'w') { |file| file.puts text } if text
|
176
|
+
rescue Exception => e
|
177
|
+
action_handler.report_progress "WARN: Failed to delete entries for #{name} (#{ip_address}) from known_hosts file: '#{f}'! "
|
178
|
+
puts "Error: #{e.message}"
|
185
179
|
end
|
186
180
|
end
|
187
|
-
|
188
|
-
end # End if machine_spec.reference
|
181
|
+
end
|
189
182
|
end # destroy_machine method end
|
190
183
|
|
191
184
|
|
@@ -193,6 +186,32 @@ module Chef::Provisioning
|
|
193
186
|
machine_for(machine_spec, machine_options)
|
194
187
|
end
|
195
188
|
|
189
|
+
private
|
190
|
+
|
191
|
+
def ip_from_machine(machine_spec, machine_options)
|
192
|
+
return machine_options[:driver_options][:ip_address] if machine_options[:driver_options][:ip_address]
|
193
|
+
|
194
|
+
id, connection = machine_options[:driver_options][:connections].find { |_id, c| c[:bootstrap] == true }
|
195
|
+
raise 'Must specify a connection to use to bootstrap!' unless id && connection # TODO: Try first connection anyways?
|
196
|
+
return connection[:ip4Address] if connection[:ip4Address] # Return static IP if set
|
197
|
+
# Look for dhcp address given to this connection
|
198
|
+
if machine_spec.data['normal']['icsp'] && machine_spec.data['normal']['icsp']['interfaces']
|
199
|
+
interface = machine_spec.data['normal']['icsp']['interfaces'].find { |i| i['oneViewId'] == id }
|
200
|
+
if interface
|
201
|
+
addr = interface['ipv4Addr'] || interface['ipv6Addr']
|
202
|
+
return addr if addr
|
203
|
+
end
|
204
|
+
end
|
205
|
+
profile = OneviewSDK::ServerProfile.find_by(@ov, serialNumber: machine_spec.reference['serial_number']).first
|
206
|
+
my_server = get_icsp_server_by_sn(machine_spec.reference['serial_number'])
|
207
|
+
mac = profile['connections'].find { |x| x['id'] == id }['mac']
|
208
|
+
interface = my_server['interfaces'].find { |i| i['macAddr'] == mac }
|
209
|
+
addr = interface['ipv4Addr'] || interface['ipv6Addr']
|
210
|
+
addr ||= my_server['hostName'] # Fall back on hostName
|
211
|
+
Chef::Log.warn "IP address for '#{machine_spec.name}' not specified and could not be retrieved!" unless addr
|
212
|
+
addr
|
213
|
+
end
|
214
|
+
|
196
215
|
end # class end
|
197
216
|
|
198
217
|
# Additional No-Op classes to nil return when a :converge is called
|