class Chef::Provider::Service::Systemd

Attributes

status_check_success[RW]

Public Class Methods

supports?(resource, action) click to toggle source
# File lib/chef/provider/service/systemd.rb, line 35
def self.supports?(resource, action)
  service_script_exist?(:systemd, resource.service_name)
end

Public Instance Methods

define_resource_requirements() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 69
def define_resource_requirements
  shared_resource_requirements
  requirements.assert(:all_actions) do |a|
    a.assertion { status_check_success }
    # We won't stop in any case, but in whyrun warn and tell what we're doing.
    a.whyrun ["Failed to determine status of #{new_resource}, using command #{new_resource.status_command}.",
      "Assuming service would have been installed and is disabled"]
  end
end
disable_service() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 180
def disable_service
  if current_resource.masked || current_resource.indirect
    logger.debug("#{new_resource} cannot be disabled: it is masked or indirect")
    return
  end
  options, args = get_systemctl_options_args
  shell_out!(systemctl_path, args, "disable", new_resource.service_name, **options)
end
enable_service() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 171
def enable_service
  if current_resource.masked || current_resource.indirect
    logger.debug("#{new_resource} cannot be enabled: it is masked or indirect")
    return
  end
  options, args = get_systemctl_options_args
  shell_out!(systemctl_path, args, "enable", new_resource.service_name, **options)
end
get_systemctl_options_args() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 103
def get_systemctl_options_args
  if new_resource.user
    raise NotImplementedError, "#{new_resource} does not support the user property on a target_mode host (yet)" if Chef::Config.target_mode?

    uid = Etc.getpwnam(new_resource.user).uid
    options = {
      environment: {
        "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{uid}/bus",
      },
      user: new_resource.user,
    }
    args = "--user"
  else
    options = {}
    args = "--system"
  end

  [options, args]
end
is_active?() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 199
def is_active?
  # Note: "activating" is not active (as with type=notify or a oneshot)
  systemd_service_status["ActiveState"] == "active"
end
is_enabled?() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 204
def is_enabled?
  # if the service is in sysv compat mode, shellout to determine if enabled
  if systemd_service_status["UnitFileState"] == "bad"
    options, args = get_systemctl_options_args
    return shell_out(systemctl_path, args, "is-enabled", new_resource.service_name, "--quiet", **options).exitstatus == 0
  end
  # See https://github.com/systemd/systemd/blob/master/src/systemctl/systemctl-is-enabled.c
  # Note: enabled-runtime is excluded because this is volatile, and the state of enabled-runtime
  # specifically means that the service is not enabled
  %w{enabled static generated alias indirect}.include?(systemd_service_status["UnitFileState"])
end
is_indirect?() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 216
def is_indirect?
  systemd_service_status["UnitFileState"] == "indirect"
end
is_masked?() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 220
def is_masked?
  # Note: masked-runtime is excluded, because runtime is volatile, and
  # because masked-runtime is not masked.
  systemd_service_status["UnitFileState"] == "masked"
end
load_current_resource() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 39
def load_current_resource
  @current_resource = Chef::Resource::Service.new(new_resource.name)
  current_resource.service_name(new_resource.service_name)
  @status_check_success = true

  if new_resource.status_command
    logger.trace("#{new_resource} you have specified a status command, running..")

    unless shell_out(new_resource.status_command).error?
      current_resource.running(true)
    else
      @status_check_success = false
      current_resource.running(false)
      current_resource.enabled(false)
      current_resource.masked(false)
      current_resource.indirect(false)
    end
  else
    current_resource.running(is_active?)
  end

  current_resource.enabled(is_enabled?)
  current_resource.masked(is_masked?)
  current_resource.indirect(is_indirect?)
  current_resource
end
mask_service() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 189
def mask_service
  options, args = get_systemctl_options_args
  shell_out!(systemctl_path, args, "mask", new_resource.service_name, **options)
end
reload_service() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 158
def reload_service
  if new_resource.reload_command
    super
  else
    if current_resource.running
      options, args = get_systemctl_options_args
      shell_out!(systemctl_path, args, "reload", new_resource.service_name, default_env: false, **options)
    else
      start_service
    end
  end
end
restart_service() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 149
def restart_service
  if new_resource.restart_command
    super
  else
    options, args = get_systemctl_options_args
    shell_out!(systemctl_path, args, "restart", new_resource.service_name, default_env: false, **options)
  end
end
start_service() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 123
def start_service
  if current_resource.running
    logger.debug("#{new_resource} already running, not starting")
  else
    if new_resource.start_command
      super
    else
      options, args = get_systemctl_options_args
      shell_out!(systemctl_path, args, "start", new_resource.service_name, default_env: false, **options)
    end
  end
end
stop_service() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 136
def stop_service
  unless current_resource.running
    logger.debug("#{new_resource} not running, not stopping")
  else
    if new_resource.stop_command
      super
    else
      options, args = get_systemctl_options_args
      shell_out!(systemctl_path, args, "stop", new_resource.service_name, default_env: false, **options)
    end
  end
end
systemd_service_status() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 79
def systemd_service_status
  @systemd_service_status ||= begin
    # Collect all the status information for a service and returns it at once
    options, args = get_systemctl_options_args
    s = shell_out!(systemctl_path, args, "show", "-p", "UnitFileState", "-p", "ActiveState", new_resource.service_name, **options)
    # e.g. /bin/systemctl --system show  -p UnitFileState -p ActiveState sshd.service
    # Returns something like:
    # ActiveState=active
    # UnitFileState=enabled
    status = {}
    s.stdout.each_line do |line|
      k, v = line.strip.split("=")
      status[k] = v
    end

    # Assert requisite keys exist
    unless status.key?("UnitFileState") && status.key?("ActiveState")
      raise Chef::Exceptions::Service, "'#{systemctl_path} show' not reporting status for #{new_resource.service_name}!"
    end

    status
  end
end
unmask_service() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 194
def unmask_service
  options, args = get_systemctl_options_args
  shell_out!(systemctl_path, args, "unmask", new_resource.service_name, **options)
end
user_services_requirements() click to toggle source

systemd supports user services just fine

# File lib/chef/provider/service/systemd.rb, line 67
def user_services_requirements; end

Private Instance Methods

systemctl_path() click to toggle source
# File lib/chef/provider/service/systemd.rb, line 228
def systemctl_path
  if @systemctl_path.nil?
    @systemctl_path = which("systemctl")
  end
  @systemctl_path
end