summaryrefslogtreecommitdiff
path: root/lib/chef/application/windows_service_manager.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef/application/windows_service_manager.rb')
-rw-r--r--lib/chef/application/windows_service_manager.rb205
1 files changed, 0 insertions, 205 deletions
diff --git a/lib/chef/application/windows_service_manager.rb b/lib/chef/application/windows_service_manager.rb
deleted file mode 100644
index 4f0de26411..0000000000
--- a/lib/chef/application/windows_service_manager.rb
+++ /dev/null
@@ -1,205 +0,0 @@
-#
-# Author:: Seth Chisamore (<schisamo@chef.io>)
-# Copyright:: Copyright (c) Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# 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.
-#
-
-if RUBY_PLATFORM.match?(/mswin|mingw32|windows/)
- require "win32/service"
-end
-require_relative "../config"
-require "mixlib/cli" unless defined?(Mixlib::CLI)
-require "chef-utils/dist" unless defined?(ChefUtils::Dist)
-
-class Chef
- class Application
- #
- # This class is used to create and manage a windows service.
- # Service should be created using Daemon class from
- # win32/service gem.
- # For an example see: Chef::Application::WindowsService
- #
- # Outside programs are expected to use this class to manage
- # windows services.
- #
- class WindowsServiceManager
- include Mixlib::CLI
-
- option :action,
- short: "-a ACTION",
- long: "--action ACTION",
- default: "status",
- description: "Action to carry out on #{ChefUtils::Dist::Infra::SHORT}-service (install, uninstall, status, start, stop, pause, or resume)."
-
- option :config_file,
- short: "-c CONFIG",
- long: "--config CONFIG",
- default: "#{ChefConfig::Config.c_chef_dir}/client.rb",
- description: "The configuration file to use for #{ChefUtils::Dist::Infra::PRODUCT} runs."
-
- option :log_location,
- short: "-L LOGLOCATION",
- long: "--logfile LOGLOCATION",
- description: "Set the log file location for #{ChefUtils::Dist::Infra::SHORT}-service."
-
- option :help,
- short: "-h",
- long: "--help",
- description: "Show this help message.",
- on: :tail,
- boolean: true,
- show_options: true,
- exit: 0
-
- option :version,
- short: "-v",
- long: "--version",
- description: "Show #{ChefUtils::Dist::Infra::PRODUCT} version.",
- boolean: true,
- proc: lambda { |v| puts "#{ChefUtils::Dist::Infra::PRODUCT}: #{::Chef::VERSION}" },
- exit: 0
-
- def initialize(service_options)
- # having to call super in initialize is the most annoying
- # anti-pattern :(
- super()
-
- raise ArgumentError, "Service definition is not provided" if service_options.nil?
-
- required_options = %i{service_name service_display_name service_description service_file_path}
-
- required_options.each do |req_option|
- unless service_options.key?(req_option)
- raise ArgumentError, "Service definition doesn't contain required option #{req_option}"
- end
- end
-
- @service_name = service_options[:service_name]
- @service_display_name = service_options[:service_display_name]
- @service_description = service_options[:service_description]
- @service_file_path = service_options[:service_file_path]
- @service_start_name = service_options[:run_as_user]
- @password = service_options[:run_as_password]
- @delayed_start = service_options[:delayed_start]
- @dependencies = service_options[:dependencies]
- end
-
- def run(params = ARGV)
- parse_options(params)
-
- case config[:action]
- when "install"
- if service_exists?
- puts "Service #{@service_name} already exists on the system."
- else
- ruby = File.join(RbConfig::CONFIG["bindir"], "ruby")
-
- opts = ""
- opts << " -c #{config[:config_file]}" if config[:config_file]
- opts << " -L #{config[:log_location]}" if config[:log_location]
-
- # Quote the full paths to deal with possible spaces in the path name.
- # Also ensure all forward slashes are backslashes
- cmd = "\"#{ruby}\" \"#{@service_file_path}\" #{opts}".gsub(File::SEPARATOR, File::ALT_SEPARATOR)
-
- ::Win32::Service.new(
- service_name: @service_name,
- display_name: @service_display_name,
- description: @service_description,
- # Prior to 0.8.5, win32-service creates interactive services by default,
- # and we don't want that, so we need to override the service type.
- service_type: ::Win32::Service::SERVICE_WIN32_OWN_PROCESS,
- start_type: ::Win32::Service::SERVICE_AUTO_START,
- binary_path_name: cmd,
- service_start_name: @service_start_name,
- password: @password,
- dependencies: @dependencies
- )
- unless @delayed_start.nil?
- ::Win32::Service.configure(
- service_name: @service_name,
- delayed_start: @delayed_start
- )
- end
- puts "Service '#{@service_name}' has successfully been installed."
- end
- when "status"
- if !service_exists?
- puts "Service #{@service_name} doesn't exist on the system."
- else
- puts "State of #{@service_name} service is: #{current_state}"
- end
- when "start"
- # TODO: allow override of startup parameters here?
- take_action("start", RUNNING)
- when "stop"
- take_action("stop", STOPPED)
- when "uninstall", "delete"
- take_action("stop", STOPPED)
- unless service_exists?
- puts "Service #{@service_name} doesn't exist on the system."
- else
- ::Win32::Service.delete(@service_name)
- puts "Service #{@service_name} deleted"
- end
- when "pause"
- take_action("pause", PAUSED)
- when "resume"
- take_action("resume", RUNNING)
- end
- end
-
- private
-
- # Just some state constants
- STOPPED = "stopped".freeze
- RUNNING = "running".freeze
- PAUSED = "paused".freeze
-
- def service_exists?
- ::Win32::Service.exists?(@service_name)
- end
-
- def take_action(action = nil, desired_state = nil)
- if service_exists?
- if current_state != desired_state
- ::Win32::Service.send(action, @service_name)
- wait_for_state(desired_state)
- puts "Service '#{@service_name}' is now '#{current_state}'."
- else
- puts "Service '#{@service_name}' is already '#{desired_state}'."
- end
- else
- puts "Cannot '#{action}' service '#{@service_name}'"
- puts "Service #{@service_name} doesn't exist on the system."
- end
- end
-
- def current_state
- ::Win32::Service.status(@service_name).current_state
- end
-
- # Helper method that waits for a status to change its state since state
- # changes aren't usually instantaneous.
- def wait_for_state(desired_state)
- while current_state != desired_state
- puts "One moment... #{current_state}"
- sleep 1
- end
- end
-
- end
- end
-end