summaryrefslogtreecommitdiffstats
path: root/lib/puppet/provider/service/freebsd.rb
blob: 3ff81fdfbf1f2f6bbbf214b278820f6524580799 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
Puppet::Type.type(:service).provide :freebsd, :parent => :init do

    desc "Provider for FreeBSD. Makes use of rcvar argument of init scripts and parses/edits rc files."

    confine :operatingsystem => [:freebsd]
    defaultfor :operatingsystem => [:freebsd]

    @@rcconf = '/etc/rc.conf'
    @@rcconf_local = '/etc/rc.conf.local'
    @@rcconf_dir = '/etc/rc.conf.d'

    def self.defpath
        superclass.defpath
    end

    # Executing an init script with the 'rcvar' argument returns
    # the service name, rcvar name and whether it's enabled/disabled
    def rcvar
        rcvar = execute([self.initscript, :rcvar], :failonfail => true, :squelch => false)
        rcvar = rcvar.split("\n")
        rcvar
    end

    # Extract service name
    def service_name
        name = self.rcvar[0]
        self.error("No service name found in rcvar") if name.nil?
        name = name.gsub!(/# (.*)/, '\1')
        self.error("Service name is empty") if name.nil?
        self.debug("Service name is #{name}")
        name
    end

    # Extract rcvar name
    def rcvar_name
        name = self.rcvar[1]
        self.error("No rcvar name found in rcvar") if name.nil?
        name = name.gsub!(/(.*)_enable=(.*)/, '\1')
        self.error("rcvar name is empty") if name.nil?
        self.debug("rcvar name is #{name}")
        name
    end

    # Extract rcvar value
    def rcvar_value
        value = self.rcvar[1]
        self.error("No rcvar value found in rcvar") if value.nil?
        value = value.gsub!(/(.*)_enable=\"?(.*)\"?/, '\2')
        self.error("rcvar value is empty") if value.nil?
        self.debug("rcvar value is #{value}")
        value
    end

    # Edit rc files and set the service to yes/no
    def rc_edit(yesno)
        service = self.service_name
        rcvar = self.rcvar_name
        self.debug("Editing rc files: setting #{rcvar} to #{yesno} for #{service}")
        self.rc_add(service, rcvar, yesno) if not self.rc_replace(service, rcvar, yesno)
    end

    # Try to find an existing setting in the rc files
    # and replace the value
    def rc_replace(service, rcvar, yesno)
        success = false
        # Replace in all files, not just in the first found with a match
        [@@rcconf, @@rcconf_local, @@rcconf_dir + "/#{service}"].each do |filename|
            if File.exists?(filename)
                s = File.read(filename)
                if s.gsub!(/(#{rcvar}_enable)=\"?(YES|NO)\"?/, "\\1=\"#{yesno}\"")
                    File.open(filename, File::WRONLY) { |f| f << s }
                    self.debug("Replaced in #{filename}")
                    success = true
                end
            end
        end
        success
    end

    # Add a new setting to the rc files
    def rc_add(service, rcvar, yesno)
        append = "\n\# Added by Puppet\n#{rcvar}_enable=\"#{yesno}\""
        # First, try the one-file-per-service style
        if File.exists?(@@rcconf_dir)
            File.open(@@rcconf_dir + "/#{service}", File::WRONLY | File::APPEND | File::CREAT, 0644) {
                |f| f << append
                self.debug("Appended to #{f.path}")
            }
        else
            # Else, check the local rc file first, but don't create it
            if File.exists?(@@rcconf_local)
                File.open(@@rcconf_local, File::WRONLY | File::APPEND) {
                    |f| f << append
                    self.debug("Appended to #{f.path}")
                }
            else
                # At last use the standard rc.conf file
                File.open(@@rcconf, File::WRONLY | File::APPEND | File::CREAT, 0644) {
                    |f| f << append
                    self.debug("Appended to #{f.path}")
                }
            end
        end
    end

    def enabled?
        if /YES$/ =~ self.rcvar_value
            self.debug("Is enabled")
            return :true
        end
        self.debug("Is disabled")
        :false
    end

    def enable
        self.debug("Enabling")
        self.rc_edit("YES")
    end

    def disable
        self.debug("Disabling")
        self.rc_edit("NO")
    end

    def startcmd
        [self.initscript, :onestart]
    end

    def stopcmd
        [self.initscript, :onestop]
    end

    def statuscmd
        [self.initscript, :onestatus]
    end

end