class Chef::Provider::Service::Windows
Constants
- AUTO_START
Win32::Service.get_start_type
- CONTINUE_PENDING
- DISABLED
- MANUAL
- PAUSED
- PAUSE_PENDING
- RUNNING
Win32::Service.get_current_state
- SERVICE_RIGHT
- START_PENDING
- STOPPED
- STOP_PENDING
- TIMEOUT
Public Instance Methods
action_configure_startup()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 246 def action_configure_startup startup_type = @new_resource.startup_type if current_startup_type != startup_type converge_by("set service #{@new_resource} startup type to #{startup_type}") do set_startup_type(startup_type) end else logger.trace("#{@new_resource} startup_type already #{startup_type} - nothing to do") end converge_delayed_start # Avoid changing enabled from true/false for now @new_resource.enabled(nil) end
action_disable()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 233 def action_disable if current_startup_type != :disabled converge_by("disable service #{@new_resource}") do disable_service logger.info("#{@new_resource} disabled") end else logger.trace("#{@new_resource} already disabled - nothing to do") end load_new_resource_state @new_resource.enabled(false) end
action_enable()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 220 def action_enable if current_startup_type != :automatic converge_by("enable service #{@new_resource}") do enable_service logger.info("#{@new_resource} enabled") end else logger.trace("#{@new_resource} already enabled - nothing to do") end load_new_resource_state @new_resource.enabled(true) end
disable_service()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 173 def disable_service if Win32::Service.exists?(@new_resource.service_name) set_startup_type(:disabled) else logger.trace "#{@new_resource} does not exist - nothing to do" end end
enable_service()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 165 def enable_service if Win32::Service.exists?(@new_resource.service_name) set_startup_type(:automatic) else logger.trace "#{@new_resource} does not exist - nothing to do" end end
load_current_resource()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 54 def load_current_resource @current_resource = Chef::Resource::WindowsService.new(new_resource.name) current_resource.service_name(new_resource.service_name) if Win32::Service.exists?(current_resource.service_name) current_resource.running(current_state == RUNNING) logger.trace "#{new_resource} running: #{current_resource.running}" case current_startup_type when :automatic current_resource.enabled(true) when :disabled current_resource.enabled(false) end logger.trace "#{new_resource} enabled: #{current_resource.enabled}" config_info = Win32::Service.config_info(current_resource.service_name) current_resource.service_type(get_service_type(config_info.service_type)) if config_info.service_type current_resource.startup_type(start_type_to_sym(config_info.start_type)) if config_info.start_type current_resource.error_control(get_error_control(config_info.error_control)) if config_info.error_control current_resource.binary_path_name(config_info.binary_path_name) if config_info.binary_path_name current_resource.load_order_group(config_info.load_order_group) if config_info.load_order_group current_resource.dependencies(config_info.dependencies) if config_info.dependencies current_resource.run_as_user(config_info.service_start_name) if config_info.service_start_name current_resource.display_name(config_info.display_name) if config_info.display_name current_resource.delayed_start(current_delayed_start) if current_delayed_start end current_resource end
restart_service()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 150 def restart_service if Win32::Service.exists?(@new_resource.service_name) if @new_resource.restart_command logger.trace "#{@new_resource} restarting service using the given restart_command" shell_out!(@new_resource.restart_command) else stop_service start_service end @new_resource.updated_by_last_action(true) else logger.trace "#{@new_resource} does not exist - nothing to do" end end
start_service()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 84 def start_service if Win32::Service.exists?(@new_resource.service_name) configure_service_run_as_properties state = current_state if state == RUNNING logger.trace "#{@new_resource} already started - nothing to do" elsif state == START_PENDING logger.trace "#{@new_resource} already sent start signal - waiting for start" wait_for_state(RUNNING) elsif state == STOPPED if @new_resource.start_command logger.trace "#{@new_resource} starting service using the given start_command" shell_out!(@new_resource.start_command) else spawn_command_thread do begin Win32::Service.start(@new_resource.service_name) rescue SystemCallError => ex if ex.errno == ERROR_SERVICE_LOGON_FAILED logger.error ex.message raise Chef::Exceptions::Service, "Service #{@new_resource} did not start due to a logon failure (error #{ERROR_SERVICE_LOGON_FAILED}): possibly the specified user '#{@new_resource.run_as_user}' does not have the 'log on as a service' privilege, or the password is incorrect." else raise ex end end end wait_for_state(RUNNING) end @new_resource.updated_by_last_action(true) else raise Chef::Exceptions::Service, "Service #{@new_resource} can't be started from state [#{state}]" end else logger.trace "#{@new_resource} does not exist - nothing to do" end end
stop_service()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 123 def stop_service if Win32::Service.exists?(@new_resource.service_name) state = current_state if state == RUNNING if @new_resource.stop_command logger.trace "#{@new_resource} stopping service using the given stop_command" shell_out!(@new_resource.stop_command) else spawn_command_thread do Win32::Service.stop(@new_resource.service_name) end wait_for_state(STOPPED) end @new_resource.updated_by_last_action(true) elsif state == STOPPED logger.trace "#{@new_resource} already stopped - nothing to do" elsif state == STOP_PENDING logger.trace "#{@new_resource} already sent stop signal - waiting for stop" wait_for_state(STOPPED) else raise Chef::Exceptions::Service, "Service #{@new_resource} can't be stopped from state [#{state}]" end else logger.trace "#{@new_resource} does not exist - nothing to do" end end
Private Instance Methods
canonicalize_username(username)
click to toggle source
# File lib/chef/provider/service/windows.rb, line 313 def canonicalize_username(username) username.sub(/^\.?\\+/, "") end
clean_username_for_path(username)
click to toggle source
remove characters that make for broken or wonky filenames.
# File lib/chef/provider/service/windows.rb, line 309 def clean_username_for_path(username) username.gsub(/[\/\\. ]+/, "_") end
configure_service_run_as_properties()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 264 def configure_service_run_as_properties return unless new_resource.property_is_set?(:run_as_user) new_config = { service_name: new_resource.service_name, service_start_name: new_resource.run_as_user, password: new_resource.run_as_password, }.reject { |k, v| v.nil? || v.length == 0 } Win32::Service.configure(new_config) logger.info "#{new_resource} configured." grant_service_logon(new_resource.run_as_user) if new_resource.run_as_user.casecmp("localsystem") != 0 end
converge_delayed_start()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 397 def converge_delayed_start converge_if_changed :delayed_start do config = {} config[:service_name] = new_resource.service_name config[:delayed_start] = new_resource.delayed_start ? 1 : 0 Win32::Service.configure(config) end end
current_delayed_start()
click to toggle source
Queries the delayed auto-start setting of the auto-start service. If the service is not auto-start, this will return nil.
@return [Boolean, nil]
# File lib/chef/provider/service/windows.rb, line 285 def current_delayed_start case Win32::Service.delayed_start(new_resource.service_name) when 0 false when 1 true end end
current_startup_type()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 321 def current_startup_type start_type = Win32::Service.config_info(@new_resource.service_name).start_type start_type_to_sym(start_type) end
current_state()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 317 def current_state Win32::Service.status(@new_resource.service_name).current_state end
get_error_control(error_control)
click to toggle source
# File lib/chef/provider/service/windows.rb, line 470 def get_error_control(error_control) case error_control when "critical" SERVICE_ERROR_CRITICAL when "ignore" SERVICE_ERROR_IGNORE when "normal" SERVICE_ERROR_NORMAL when "severe" SERVICE_ERROR_SEVERE else nil end end
get_service_type(service_type)
click to toggle source
# File lib/chef/provider/service/windows.rb, line 425 def get_service_type(service_type) case service_type when "file system driver" SERVICE_FILE_SYSTEM_DRIVER when "kernel driver" SERVICE_KERNEL_DRIVER when "own process" SERVICE_WIN32_OWN_PROCESS when "share process" SERVICE_WIN32_SHARE_PROCESS when "recognizer driver" SERVICE_RECOGNIZER_DRIVER when "driver" SERVICE_DRIVER when "win32" SERVICE_WIN32 when "all" SERVICE_TYPE_ALL when "own process, interactive" SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS when "share process, interactive" SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_SHARE_PROCESS else raise("Unsupported service type, #{service_type}. Submit bug request to fix.") end end
get_start_type(start_type)
click to toggle source
@return [Integer]
# File lib/chef/provider/service/windows.rb, line 453 def get_start_type(start_type) case start_type when "auto start" SERVICE_AUTO_START when "boot start" SERVICE_BOOT_START when "demand start" SERVICE_DEMAND_START when "disabled" SERVICE_DISABLED when "system start" SERVICE_SYSTEM_START else raise("Unsupported start type, #{start_type}. Submit bug request to fix.") end end
grant_service_logon(username)
click to toggle source
# File lib/chef/provider/service/windows.rb, line 294 def grant_service_logon(username) return if Chef::ReservedNames::Win32::Security.get_account_right(canonicalize_username(username)).include?(SERVICE_RIGHT) begin Chef::ReservedNames::Win32::Security.add_account_right(canonicalize_username(username), SERVICE_RIGHT) rescue Chef::Exceptions::Win32APIError => err logger.fatal "Logon-as-service grant failed with output: #{err}" raise Chef::Exceptions::Service, "Logon-as-service grant failed for #{username}: #{err}" end logger.info "Grant logon-as-service to user '#{username}' successful." true end
resource_timeout()
click to toggle source
# File lib/chef/provider/service/windows.rb, line 337 def resource_timeout @resource_timeout ||= @new_resource.timeout || TIMEOUT end
set_startup_type(type)
click to toggle source
Takes Win32::Service start_types
# File lib/chef/provider/service/windows.rb, line 363 def set_startup_type(type) startup_type = startup_type_to_int(type) logger.trace "#{@new_resource.name} setting start_type to #{type}" Win32::Service.configure( service_name: @new_resource.service_name, start_type: startup_type ) @new_resource.updated_by_last_action(true) end
spawn_command_thread() { || ... }
click to toggle source
# File lib/chef/provider/service/windows.rb, line 341 def spawn_command_thread worker = Thread.new do yield end Timeout.timeout(resource_timeout) do worker.join end end
start_type_to_sym(start_type)
click to toggle source
@return [Symbol]
# File lib/chef/provider/service/windows.rb, line 408 def start_type_to_sym(start_type) case start_type when "auto start" :automatic when "boot start" raise("Unsupported start type, #{start_type}. Submit bug request to fix.") when "demand start" :manual when "disabled" :disabled when "system start" raise("Unsupported start type, #{start_type}. Submit bug request to fix.") else raise("Unsupported start type, #{start_type}. Submit bug request to fix.") end end
startup_type_to_int(type)
click to toggle source
@param type [Symbol] @return [Integer] @raise [Chef::Exceptions::ConfigurationError] if the startup type is
not supported.
@see Chef::Resource::WindowsService::ALLOWED_START_TYPES
# File lib/chef/provider/service/windows.rb, line 356 def startup_type_to_int(type) Chef::Resource::WindowsService::ALLOWED_START_TYPES.fetch(type) do raise Chef::Exceptions::ConfigurationError, "#{@new_resource.name}: Startup type '#{type}' is not supported" end end
wait_for_state(desired_state)
click to toggle source
Helper method that waits for a status to change its state since state changes aren't usually instantaneous.
# File lib/chef/provider/service/windows.rb, line 328 def wait_for_state(desired_state) retries = 0 loop do break if current_state == desired_state raise Timeout::Error if ( retries += 1 ) > resource_timeout sleep 1 end end
windows_service_config(action = :create)
click to toggle source
# File lib/chef/provider/service/windows.rb, line 374 def windows_service_config(action = :create) config = {} config[:service_name] = new_resource.service_name config[:display_name] = new_resource.display_name if new_resource.display_name config[:service_type] = new_resource.service_type if new_resource.service_type config[:start_type] = startup_type_to_int(new_resource.startup_type) if new_resource.startup_type config[:error_control] = new_resource.error_control if new_resource.error_control config[:binary_path_name] = new_resource.binary_path_name if new_resource.binary_path_name config[:load_order_group] = new_resource.load_order_group if new_resource.load_order_group config[:dependencies] = new_resource.dependencies if new_resource.dependencies config[:service_start_name] = new_resource.run_as_user unless new_resource.run_as_user.empty? config[:password] = new_resource.run_as_password unless new_resource.run_as_user.empty? || new_resource.run_as_password.empty? config[:description] = new_resource.description if new_resource.description case action when :create config[:desired_access] = new_resource.desired_access if new_resource.desired_access end config end