330 lines
18 KiB
Ruby
330 lines
18 KiB
Ruby
#
|
|
# Author:: Kendrick Martin (kendrick.martin@webtrends.com)
|
|
# Contributor:: David Dvorak (david.dvorak@webtrends.com)
|
|
# Cookbook:: iis
|
|
# Provider:: pool
|
|
#
|
|
# Copyright:: 2011-2016, Webtrends Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
|
|
require 'chef/mixin/shell_out'
|
|
require 'rexml/document'
|
|
|
|
include Chef::Mixin::ShellOut
|
|
include REXML
|
|
include Opscode::IIS::Helper
|
|
include Opscode::IIS::Processors
|
|
|
|
action :add do
|
|
if !@current_resource.exists
|
|
cmd = "#{appcmd(node)} add apppool /name:\"#{new_resource.pool_name}\""
|
|
if new_resource.no_managed_code
|
|
cmd << ' /managedRuntimeVersion:'
|
|
elsif new_resource.runtime_version
|
|
cmd << " /managedRuntimeVersion:v#{new_resource.runtime_version}"
|
|
end
|
|
cmd << " /managedPipelineMode:#{new_resource.pipeline_mode.capitalize}" if new_resource.pipeline_mode
|
|
cmd << ' /commit:\"MACHINE/WEBROOT/APPHOST\"'
|
|
Chef::Log.debug(cmd)
|
|
shell_out!(cmd)
|
|
configure
|
|
new_resource.updated_by_last_action(true)
|
|
Chef::Log.info('App pool created')
|
|
else
|
|
Chef::Log.debug("#{new_resource} pool already exists - nothing to do")
|
|
end
|
|
end
|
|
|
|
action :config do
|
|
new_resource.updated_by_last_action(true) if configure
|
|
end
|
|
|
|
action :delete do
|
|
if @current_resource.exists
|
|
shell_out!("#{appcmd(node)} delete apppool \"#{site_identifier}\"")
|
|
new_resource.updated_by_last_action(true)
|
|
Chef::Log.info("#{new_resource} deleted")
|
|
else
|
|
Chef::Log.debug("#{new_resource} pool does not exist - nothing to do")
|
|
end
|
|
end
|
|
|
|
action :start do
|
|
if !@current_resource.running
|
|
shell_out!("#{appcmd(node)} start apppool \"#{site_identifier}\"")
|
|
new_resource.updated_by_last_action(true)
|
|
Chef::Log.info("#{new_resource} started")
|
|
else
|
|
Chef::Log.debug("#{new_resource} already running - nothing to do")
|
|
end
|
|
end
|
|
|
|
action :stop do
|
|
if @current_resource.running
|
|
shell_out!("#{appcmd(node)} stop apppool \"#{site_identifier}\"")
|
|
new_resource.updated_by_last_action(true)
|
|
Chef::Log.info("#{new_resource} stopped")
|
|
else
|
|
Chef::Log.debug("#{new_resource} already stopped - nothing to do")
|
|
end
|
|
end
|
|
|
|
action :restart do
|
|
shell_out!("#{appcmd(node)} stop APPPOOL \"#{site_identifier}\"")
|
|
sleep 2
|
|
shell_out!("#{appcmd(node)} start APPPOOL \"#{site_identifier}\"")
|
|
new_resource.updated_by_last_action(true)
|
|
Chef::Log.info("#{new_resource} restarted")
|
|
end
|
|
|
|
action :recycle do
|
|
shell_out!("#{appcmd(node)} recycle APPPOOL \"#{site_identifier}\"")
|
|
new_resource.updated_by_last_action(true)
|
|
Chef::Log.info("#{new_resource} recycled")
|
|
end
|
|
|
|
def load_current_resource
|
|
@current_resource = Chef::Resource::IisPool.new(new_resource.name)
|
|
@current_resource.pool_name(new_resource.pool_name)
|
|
cmd = shell_out("#{appcmd(node)} list apppool")
|
|
# APPPOOL "DefaultAppPool" (MgdVersion:v2.0,MgdMode:Integrated,state:Started)
|
|
Chef::Log.debug("#{new_resource} list apppool command output: #{cmd.stdout}")
|
|
if cmd.stderr.empty?
|
|
result = cmd.stdout.gsub(/\r\n?/, "\n") # ensure we have no carriage returns
|
|
result = result.match(/^APPPOOL\s\"(#{new_resource.pool_name})\"\s\(MgdVersion:(.*),MgdMode:(.*),state:(.*)\)$/i)
|
|
Chef::Log.debug("#{new_resource} current_resource match output: #{result}")
|
|
if result
|
|
@current_resource.exists = true
|
|
@current_resource.running = result[4] =~ /Started/ ? true : false
|
|
else
|
|
@current_resource.exists = false
|
|
@current_resource.running = false
|
|
end
|
|
else
|
|
log "Failed to run iis_pool action :load_current_resource, #{cmd.stderr}" do
|
|
level :warn
|
|
end
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def site_identifier
|
|
new_resource.pool_name
|
|
end
|
|
|
|
def configure
|
|
@was_updated = false
|
|
cmd_current_values = "#{appcmd(node)} list apppool \"#{new_resource.pool_name}\" /config:* /xml"
|
|
Chef::Log.debug(cmd_current_values)
|
|
cmd_current_values = shell_out(cmd_current_values)
|
|
if cmd_current_values.stderr.empty?
|
|
xml = cmd_current_values.stdout
|
|
doc = Document.new(xml)
|
|
|
|
# root items
|
|
is_new_managed_runtime_version =
|
|
if new_resource.no_managed_code
|
|
new_value?(doc.root, 'APPPOOL/@RuntimeVersion', '')
|
|
else
|
|
new_value?(doc.root, 'APPPOOL/@RuntimeVersion', "v#{new_resource.runtime_version}")
|
|
end
|
|
is_new_pipeline_mode = new_value?(doc.root, 'APPPOOL/@PipelineMode', new_resource.pipeline_mode)
|
|
|
|
# add items
|
|
if iis_version >= 7.0
|
|
is_new_auto_start = new_value?(doc.root, 'APPPOOL/add/@autoStart', new_resource.auto_start.to_s)
|
|
end
|
|
|
|
if iis_version > 7.0
|
|
is_new_start_mode = new_value?(doc.root, 'APPPOOL/add/@startMode', new_resource.start_mode.to_s)
|
|
end
|
|
|
|
is_new_queue_length = new_value?(doc.root, 'APPPOOL/add/@queueLength', new_resource.queue_length.to_s)
|
|
is_new_enable_32_bit_app_on_win_64 = new_value?(doc.root, 'APPPOOL/add/@enable32BitAppOnWin64', new_resource.thirty_two_bit.to_s)
|
|
|
|
# processModel items
|
|
is_new_max_processes = new_or_empty_value?(doc.root, 'APPPOOL/add/processModel/@maxProcesses', new_resource.max_proc.to_s)
|
|
is_new_load_user_profile = new_value?(doc.root, 'APPPOOL/add/processModel/@loadUserProfile', new_resource.load_user_profile.to_s)
|
|
if iis_version > 7.0
|
|
is_new_identity_type = new_value?(doc.root, 'APPPOOL/add/processModel/@identityType', new_resource.pool_identity.to_s)
|
|
end
|
|
is_new_user_name = new_or_empty_value?(doc.root, 'APPPOOL/add/processModel/@userName', new_resource.pool_username.to_s)
|
|
is_new_password = new_or_empty_value?(doc.root, 'APPPOOL/add/processModel/@password', new_resource.pool_password.to_s)
|
|
if iis_version > 7.0
|
|
is_new_logon_type = new_value?(doc.root, 'APPPOOL/add/processModel/@logonType', new_resource.logon_type.to_s)
|
|
end
|
|
is_new_manual_group_membership = new_value?(doc.root, 'APPPOOL/add/processModel/@manualGroupMembership', new_resource.manual_group_membership.to_s)
|
|
is_new_idle_timeout = new_value?(doc.root, 'APPPOOL/add/processModel/@idleTimeout', new_resource.idle_timeout.to_s)
|
|
if iis_version >= 8.5
|
|
is_new_idle_timeout_action = new_value?(doc.root, 'APPPOOL/add/processModel/@idleTimeoutAction', new_resource.idle_timeout_action)
|
|
end
|
|
is_new_shutdown_time_limit = new_value?(doc.root, 'APPPOOL/add/processModel/@shutdownTimeLimit', new_resource.shutdown_time_limit.to_s)
|
|
is_new_startup_time_limit = new_value?(doc.root, 'APPPOOL/add/processModel/@startupTimeLimit', new_resource.startup_time_limit.to_s)
|
|
is_new_pinging_enabled = new_value?(doc.root, 'APPPOOL/add/processModel/@pingingEnabled', new_resource.pinging_enabled.to_s)
|
|
is_new_ping_interval = new_value?(doc.root, 'APPPOOL/add/processModel/@pingInterval', new_resource.ping_interval.to_s)
|
|
is_new_ping_response_time = new_value?(doc.root, 'APPPOOL/add/processModel/@pingResponseTime', new_resource.ping_response_time.to_s)
|
|
|
|
# failure items
|
|
is_new_load_balancer_capabilities = new_value?(doc.root, 'APPPOOL/add/failure/@loadBalancerCapabilities', new_resource.load_balancer_capabilities.to_s)
|
|
is_new_orphan_worker_process = new_value?(doc.root, 'APPPOOL/add/failure/@orphanWorkerProcess', new_resource.orphan_worker_process.to_s)
|
|
is_new_orphan_action_exe = new_or_empty_value?(doc.root, 'APPPOOL/add/failure/@orphanActionExe', new_resource.orphan_action_exe.to_s)
|
|
is_new_orphan_action_params = new_or_empty_value?(doc.root, 'APPPOOL/add/failure/@orphanActionParams', new_resource.orphan_action_params.to_s)
|
|
is_new_rapid_fail_protection = new_value?(doc.root, 'APPPOOL/add/failure/@rapidFailProtection', new_resource.rapid_fail_protection.to_s)
|
|
is_new_rapid_fail_protection_interval = new_value?(doc.root, 'APPPOOL/add/failure/@rapidFailProtectionInterval', new_resource.rapid_fail_protection_interval.to_s)
|
|
is_new_rapid_fail_protection_max_crashes = new_value?(doc.root, 'APPPOOL/add/failure/@rapidFailProtectionMaxCrashes', new_resource.rapid_fail_protection_max_crashes.to_s)
|
|
is_new_auto_shutdown_exe = new_or_empty_value?(doc.root, 'APPPOOL/add/failure/@autoShutdownExe', new_resource.auto_shutdown_exe.to_s)
|
|
is_new_auto_shutdown_params = new_or_empty_value?(doc.root, 'APPPOOL/add/failure/@autoShutdownParams', new_resource.auto_shutdown_params.to_s)
|
|
|
|
# recycling items
|
|
is_new_disallow_overlapping_rotation = new_value?(doc.root, 'APPPOOL/add/recycling/@disallowOverlappingRotation', new_resource.disallow_overlapping_rotation.to_s)
|
|
is_new_disallow_rotation_on_config_change = new_value?(doc.root, 'APPPOOL/add/recycling/@disallowRotationOnConfigChange', new_resource.disallow_rotation_on_config_change.to_s)
|
|
is_new_recycle_after_time = new_or_empty_value?(doc.root, 'APPPOOL/add/recycling/periodicRestart/@time', new_resource.recycle_after_time.to_s)
|
|
is_new_recycle_at_time = new_or_empty_value?(doc.root, "APPPOOL/add/recycling/periodicRestart/schedule/add[@value='#{new_resource.recycle_at_time}']/@value", new_resource.recycle_at_time.to_s)
|
|
is_new_private_memory = new_or_empty_value?(doc.root, 'APPPOOL/add/recycling/periodicRestart/@privateMemory', new_resource.private_mem.to_s)
|
|
is_new_virtual_memory = new_or_empty_value?(doc.root, 'APPPOOL/add/recycling/periodicRestart/@memory', new_resource.virtual_mem.to_s)
|
|
is_new_log_event_on_recycle = new_or_empty_value?(doc.root, 'APPPOOL/add/recycling/@logEventOnRecycle', new_resource.log_event_on_recycle.to_s)
|
|
|
|
# cpu items
|
|
is_new_cpu_action = new_value?(doc.root, 'APPPOOL/add/cpu/@action', new_resource.cpu_action.to_s)
|
|
is_new_cpu_limit = new_value?(doc.root, 'APPPOOL/add/cpu/@limit', new_resource.cpu_limit.to_s)
|
|
is_new_cpu_smp_affinitized = new_value?(doc.root, 'APPPOOL/add/cpu/@smpAffinitized', new_resource.cpu_smp_affinitized.to_s)
|
|
is_new_cpu_reset_interval = new_value?(doc.root, 'APPPOOL/add/cpu/@resetInterval', new_resource.cpu_reset_interval.to_s)
|
|
is_new_smp_processor_affinity_mask = new_value?(doc.root, 'APPPOOL/add/cpu/@smpProcessorAffinityMask', new_resource.smp_processor_affinity_mask.floor)
|
|
is_new_smp_processor_affinity_mask_2 = new_value?(doc.root, 'APPPOOL/add/cpu/@smpProcessorAffinityMask2', new_resource.smp_processor_affinity_mask_2.floor)
|
|
|
|
# Application Pool Config
|
|
@cmd = "#{appcmd(node)} set config /section:applicationPools"
|
|
|
|
# root items
|
|
if iis_version >= 7.0
|
|
configure_application_pool(is_new_auto_start, "autoStart:#{new_resource.auto_start}")
|
|
end
|
|
|
|
if iis_version >= 7.5
|
|
configure_application_pool(is_new_start_mode, "startMode:#{new_resource.start_mode}")
|
|
end
|
|
|
|
if new_resource.no_managed_code
|
|
configure_application_pool(is_new_managed_runtime_version, 'managedRuntimeVersion:')
|
|
else
|
|
configure_application_pool(new_resource.runtime_version && is_new_managed_runtime_version, "managedRuntimeVersion:v#{new_resource.runtime_version}")
|
|
end
|
|
configure_application_pool(new_resource.pipeline_mode && is_new_pipeline_mode, "managedPipelineMode:#{new_resource.pipeline_mode}")
|
|
configure_application_pool(is_new_enable_32_bit_app_on_win_64, "enable32BitAppOnWin64:#{new_resource.thirty_two_bit}")
|
|
configure_application_pool(new_resource.queue_length && is_new_queue_length, "queueLength:#{new_resource.queue_length}")
|
|
|
|
# processModel items
|
|
configure_application_pool(new_resource.max_proc && is_new_max_processes, "processModel.maxProcesses:#{new_resource.max_proc}")
|
|
configure_application_pool(is_new_load_user_profile, "processModel.loadUserProfile:#{new_resource.load_user_profile}")
|
|
configure_application_pool(is_new_logon_type, "processModel.logonType:#{new_resource.logon_type}")
|
|
configure_application_pool(is_new_manual_group_membership, "processModel.manualGroupMembership:#{new_resource.manual_group_membership}")
|
|
configure_application_pool(is_new_idle_timeout, "processModel.idleTimeout:#{new_resource.idle_timeout}")
|
|
if iis_version >= 8.5
|
|
configure_application_pool(is_new_idle_timeout_action, "processModel.idleTimeoutAction:#{new_resource.idle_timeout_action}")
|
|
end
|
|
configure_application_pool(is_new_shutdown_time_limit, "processModel.shutdownTimeLimit:#{new_resource.shutdown_time_limit}")
|
|
configure_application_pool(is_new_startup_time_limit, "processModel.startupTimeLimit:#{new_resource.startup_time_limit}")
|
|
configure_application_pool(is_new_pinging_enabled, "processModel.pingingEnabled:#{new_resource.pinging_enabled}")
|
|
configure_application_pool(is_new_ping_interval, "processModel.pingInterval:#{new_resource.ping_interval}")
|
|
configure_application_pool(is_new_ping_response_time, "processModel.pingResponseTime:#{new_resource.ping_response_time}")
|
|
|
|
node_array = XPath.match(doc.root, 'APPPOOL/add/recycling/periodicRestart/schedule/add')
|
|
should_clear_apppool_schedules = ((new_resource.recycle_at_time && is_new_recycle_at_time) && !node_array.empty?) || (new_resource.recycle_schedule_clear && !node_array.empty?)
|
|
|
|
# recycling items
|
|
## Special case this collection removal for now.
|
|
if should_clear_apppool_schedules
|
|
@was_updated = true
|
|
is_new_recycle_at_time = true
|
|
clear_pool_schedule_cmd = "#{appcmd(node)} set config /section:applicationPools \"/-[name='#{new_resource.pool_name}'].recycling.periodicRestart.schedule\""
|
|
Chef::Log.debug(clear_pool_schedule_cmd)
|
|
shell_out!(clear_pool_schedule_cmd)
|
|
end
|
|
|
|
configure_application_pool(new_resource.recycle_after_time && is_new_recycle_after_time, "recycling.periodicRestart.time:#{new_resource.recycle_after_time}")
|
|
configure_application_pool(new_resource.recycle_at_time && is_new_recycle_at_time, "recycling.periodicRestart.schedule.[value='#{new_resource.recycle_at_time}']", '+')
|
|
configure_application_pool(new_resource.log_event_on_recycle && is_new_log_event_on_recycle, "recycling.logEventOnRecycle:#{new_resource.log_event_on_recycle}")
|
|
configure_application_pool(new_resource.private_mem && is_new_private_memory, "recycling.periodicRestart.privateMemory:#{new_resource.private_mem}")
|
|
configure_application_pool(new_resource.virtual_mem && is_new_virtual_memory, "recycling.periodicRestart.memory:#{new_resource.virtual_mem}")
|
|
configure_application_pool(is_new_disallow_rotation_on_config_change, "recycling.disallowRotationOnConfigChange:#{new_resource.disallow_rotation_on_config_change}")
|
|
configure_application_pool(is_new_disallow_overlapping_rotation, "recycling.disallowOverlappingRotation:#{new_resource.disallow_overlapping_rotation}")
|
|
|
|
# failure items
|
|
configure_application_pool(is_new_load_balancer_capabilities, "failure.loadBalancerCapabilities:#{new_resource.load_balancer_capabilities}")
|
|
configure_application_pool(is_new_orphan_worker_process, "failure.orphanWorkerProcess:#{new_resource.orphan_worker_process}")
|
|
configure_application_pool(new_resource.orphan_action_exe && is_new_orphan_action_exe, "failure.orphanActionExe:#{new_resource.orphan_action_exe}")
|
|
configure_application_pool(new_resource.orphan_action_params && is_new_orphan_action_params, "failure.orphanActionParams:#{new_resource.orphan_action_params}")
|
|
configure_application_pool(is_new_rapid_fail_protection, "failure.rapidFailProtection:#{new_resource.rapid_fail_protection}")
|
|
configure_application_pool(is_new_rapid_fail_protection_interval, "failure.rapidFailProtectionInterval:#{new_resource.rapid_fail_protection_interval}")
|
|
configure_application_pool(is_new_rapid_fail_protection_max_crashes, "failure.rapidFailProtectionMaxCrashes:#{new_resource.rapid_fail_protection_max_crashes}")
|
|
configure_application_pool(new_resource.auto_shutdown_exe && is_new_auto_shutdown_exe, "failure.autoShutdownExe:#{new_resource.auto_shutdown_exe}")
|
|
configure_application_pool(new_resource.auto_shutdown_params && is_new_auto_shutdown_params, "failure.autoShutdownParams:#{new_resource.auto_shutdown_params}")
|
|
|
|
# cpu items
|
|
configure_application_pool(is_new_cpu_action, "cpu.action:#{new_resource.cpu_action}")
|
|
configure_application_pool(is_new_cpu_limit, "cpu.limit:#{new_resource.cpu_limit}")
|
|
configure_application_pool(is_new_cpu_reset_interval, "cpu.resetInterval:#{new_resource.cpu_reset_interval}")
|
|
configure_application_pool(is_new_cpu_smp_affinitized, "cpu.smpAffinitized:#{new_resource.cpu_smp_affinitized}")
|
|
configure_application_pool(is_new_smp_processor_affinity_mask, "cpu.smpProcessorAffinityMask:#{new_resource.smp_processor_affinity_mask.floor}")
|
|
configure_application_pool(is_new_smp_processor_affinity_mask_2, "cpu.smpProcessorAffinityMask2:#{new_resource.smp_processor_affinity_mask_2.floor}")
|
|
|
|
if @cmd != "#{appcmd(node)} set config /section:applicationPools"
|
|
Chef::Log.debug(@cmd)
|
|
shell_out!(@cmd)
|
|
end
|
|
|
|
# Application Pool Identity Settings
|
|
if (new_resource.pool_username && new_resource.pool_username != '') && (is_new_user_name || is_new_password)
|
|
@was_updated = true
|
|
cmd = "#{appcmd(node)} set config /section:applicationPools"
|
|
cmd << " \"/[name='#{new_resource.pool_name}'].processModel.identityType:SpecificUser\""
|
|
cmd << " \"/[name='#{new_resource.pool_name}'].processModel.userName:#{new_resource.pool_username}\""
|
|
cmd << " \"/[name='#{new_resource.pool_name}'].processModel.password:#{new_resource.pool_password}\"" if new_resource.pool_password && new_resource.pool_password != '' && is_new_password
|
|
Chef::Log.debug(cmd)
|
|
shell_out!(cmd)
|
|
elsif (new_resource.pool_username.nil? || new_resource.pool_username == '') &&
|
|
(new_resource.pool_password.nil? || new_resource.pool_username == '') &&
|
|
(is_new_identity_type && new_resource.pool_identity != 'SpecificUser')
|
|
@was_updated = true
|
|
cmd = "#{appcmd(node)} set config /section:applicationPools"
|
|
cmd << " \"/[name='#{new_resource.pool_name}'].processModel.identityType:#{new_resource.pool_identity}\""
|
|
Chef::Log.debug(cmd)
|
|
shell_out!(cmd)
|
|
end
|
|
|
|
if @was_updated
|
|
Chef::Log.info("#{new_resource} configured application pool")
|
|
else
|
|
Chef::Log.debug("#{new_resource} application pool - nothing to do")
|
|
end
|
|
else
|
|
log "Failed to run iis_pool action :config, #{cmd_current_values.stderr}" do
|
|
level :warn
|
|
end
|
|
end
|
|
|
|
@was_updated
|
|
end
|
|
|
|
private
|
|
|
|
def configure_application_pool(condition, config, add_remove = '')
|
|
return unless condition
|
|
|
|
@was_updated = true
|
|
@cmd << " \"/#{add_remove}[name='#{new_resource.pool_name}'].#{config}\""
|
|
end
|