in cookbooks/fb_storage/libraries/storage.rb [808:1135]
def _out_of_spec
missing_partitions = []
missing_filesystems = []
mismatched_partitions = []
mismatched_filesystems = []
missing_arrays = []
mismatched_arrays = []
incomplete_arrays = {}
extra_arrays = []
@arrays.each do |device, conf|
short_device = File.basename(device)
next if conf['_skip'] || conf['raid_level'] == 'hybrid_xfs'
unless @existing_arrays.include?(short_device)
Chef::Log.debug(
"fb_storage: Array #{device} missing",
)
missing_arrays << device
mismatched_filesystems << device
next
end
existing_array = @existing_arrays[short_device]
existing_device = @existing['by_device'][device]
existing_members_set = Set.new(
existing_array['members'].map { |x| "/dev/#{x}" },
)
if existing_array['journal']
existing_members_set += Set.new(
["/dev/#{existing_array['journal']}"],
)
end
desired_members_set = Set.new(conf['members'])
if conf['journal']
desired_members_set += Set.new([conf['journal']])
end
if existing_array['level'] != conf['raid_level']
Chef::Log.warn(
"fb_storage: Array #{device} has incorrect raid_level" +
" #{existing_array['level']} vs #{conf['raid_level']}",
)
mismatched_arrays << device
mismatched_filesystems << device
next
elsif existing_members_set != desired_members_set
if existing_members_set < desired_members_set
if [existing_array['level'], conf['raid_level']].include?(0)
Chef::Log.warn(
"fb_storage: Array #{device} is missing members, " +
'but is RAID0 or should be RAID0 so treating it as a ' +
"mismatched array. Existing: #{existing_members_set.to_a} " +
"vs Desired: #{desired_members_set.to_a}",
)
mismatched_arrays << device
mismatched_filesystems << device
next
else
missing_members_set = desired_members_set - existing_members_set
unless missing_members_set <= Set.new(@maintenance_disks)
Chef::Log.info(
"fb_storage: Array #{device} is missing " +
"members: #{missing_members_set.to_a}",
)
incomplete_arrays[device] = missing_members_set.to_a
end
end
else
Chef::Log.warn(
"fb_storage: Array #{device} has incorrect members" +
" #{existing_members_set.to_a} vs #{desired_members_set.to_a}",
)
mismatched_arrays << device
mismatched_filesystems << device
next
end
end
if !existing_device || !existing_device['fs_type']
Chef::Log.warn(
"fb_storage: Array #{device} has no FS",
)
missing_filesystems << device
elsif existing_device['fs_type'] != conf['type']
current_fs = existing_device ? existing_device['fs_type'] : '(none)'
Chef::Log.warn(
"fb_storage: Array #{device} has incorrect FS" +
" #{current_fs} vs #{conf['type']}",
)
mismatched_filesystems << device
end
end
@existing_arrays.each_key do |shortarray|
array = "/dev/#{shortarray}"
next if @arrays[array]
Chef::Log.info("fb_storage: Extraneous array: #{array}")
extra_arrays << array
end
@config.each do |device, conf|
if @maintenance_disks.include?(device)
Chef::Log.info(
"fb_storage: Skipping check of #{device} because it " +
'is marked as "in_maintenance"',
)
next
end
if conf['_skip']
Chef::Log.info(
"fb_storage: Skipping check of #{device} because it " +
'is marked as "skip" in config.',
)
next
end
devparts = @existing['by_device'].to_hash.keys.select do |x|
FB::Storage.device_name_from_partition(x) == device && x != device
end
devparts.sort_by! do |part|
part.match('\d+$')[0].to_i
end
Chef::Log.debug(
"fb_storage: partitions of #{device} are: #{devparts}",
)
dev_info = @existing['by_device'][device]
if conf['whole_device']
has_whole_disk_fs = devparts.count == 1 &&
@existing['by_device'][devparts[0]].empty? &&
dev_info['fs_type']
if devparts.empty? || has_whole_disk_fs
expected_label = conf['partitions'][0]['label']
if dev_info.nil? || dev_info.empty?
Chef::Log.debug(
"fb_storage: Entire device #{device} needs " +
'filesystem',
)
missing_filesystems << device
elsif dev_info['fs_type'] != conf['partitions'][0]['type']
Chef::Log.debug(
"fb_storage: Entire device #{device} has " +
'incorrect filesystem',
)
mismatched_filesystems << device
elsif expected_label && dev_info['label'] != expected_label
mismatched_filesystems << device
Chef::Log.debug(
"fb_storage: Entire device #{device} has " +
"incorrect FS label. Expected #{expected_label}, found " +
"#{dev_info['label']}.",
)
end
else
Chef::Log.debug(
"fb_storage: Device #{device} has partitions " +
' but we want a whole-device filesystem',
)
mismatched_partitions << device
mismatched_filesystems << device
end
next
end
if devparts.empty? && !(dev_info && dev_info['fs_type'])
Chef::Log.info(
"fb_storage: #{device} has no partitions and isn't " +
'formatted',
)
missing_partitions << device
missing_filesystems += partition_names(device, conf)
next
end
if devparts.count != conf['partitions'].count
Chef::Log.warn(
"fb_storage: #{device} has the wrong number of " +
"partitions (#{devparts.count} vs #{conf['partitions'].count})",
)
mismatched_partitions << device
mismatched_filesystems += partition_names(device, conf)
next
end
devparts.each_with_index do |part, index|
Chef::Log.debug(
"fb_storage: Considering partition #{part}",
)
if conf['partitions'][index]['_swraid_array'] ||
conf['partitions'][index]['_swraid_array_journal']
Chef::Log.debug('fb_storage: skipping swraid partition')
next
end
if conf['partitions'][index]['_xfs_rt_data'] ||
conf['partitions'][index]['_xfs_rt_rescue'] ||
conf['partitions'][index]['_xfs_rt_metadata']
expected_part_name = conf['partitions'][index]['part_name']
actual_part_name = FB::Storage.get_actual_part_name(part)
if actual_part_name != expected_part_name
Chef::Log.warn("fb_storage: Partition #{part} expected to " +
"have partlabel '#{expected_part_name}', actual " +
"is '#{actual_part_name}'.")
mismatched_partitions << device
end
end
if conf['partitions'][index]['_xfs_rt_data'] ||
conf['partitions'][index]['_xfs_rt_rescue']
next
end
partinfo = @existing['by_device'][part]
expected_fs = conf['partitions'][index]['type']
expected_label = conf['partitions'][index]['label']
if !expected_label && conf['partitions'][index]['_xfs_rt_metadata']
expected_label = self.get_expected_label_for_hybrid_md_part(part)
end
if conf['partitions'][index]['_xfs_rt_metadata']
expected_fs = 'xfs'
end
if !partinfo || !partinfo['fs_type']
Chef::Log.warn(
"fb_storage: Partition #{part} has no filesystem",
)
missing_filesystems << part
elsif partinfo['fs_type'] != expected_fs
Chef::Log.warn(
"fb_storage: Partition #{part} has the wrong " +
"filesystem (#{partinfo['fs_type']} vs #{expected_fs})",
)
mismatched_filesystems << part
elsif expected_label && partinfo['label'] != expected_label
Chef::Log.warn(
"fb_storage: Partition #{part} has incorrect " +
"label. Expected #{expected_label}, found " +
"#{partinfo['label']}.",
)
mismatched_filesystems << part
end
end
end
missing_filesystems.each do |fs|
mma = @arrays.select do |_array, config|
config['raid_level'] == 'hybrid_xfs' &&
(config['members'].include?(fs) ||
config['journal'] == fs)
end
missing_filesystems += mma.keys
end
mismatched_filesystems.each do |fs|
mma = @arrays.select do |_array, config|
config['raid_level'] == 'hybrid_xfs' &&
(config['members'].include?(fs) ||
config['journal'] == fs)
end
mismatched_filesystems += mma.keys
end
{
:mismatched_partitions => mismatched_partitions.sort.uniq,
:mismatched_filesystems => mismatched_filesystems.sort.uniq,
:missing_partitions => missing_partitions.sort.uniq,
:missing_filesystems => missing_filesystems.sort.uniq,
:missing_arrays => missing_arrays.sort.uniq,
:mismatched_arrays => mismatched_arrays.sort.uniq,
:extra_arrays => extra_arrays.sort.uniq,
:incomplete_arrays => incomplete_arrays,
}
end