dust-deploy 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +154 -0
- data/Rakefile +1 -0
- data/bin/dust +215 -0
- data/dust.gemspec +28 -0
- data/lib/dust.rb +6 -0
- data/lib/dust/convert_size.rb +21 -0
- data/lib/dust/print_status.rb +57 -0
- data/lib/dust/recipes/aliases.rb +13 -0
- data/lib/dust/recipes/basic_setup.rb +35 -0
- data/lib/dust/recipes/debsecan.rb +44 -0
- data/lib/dust/recipes/duplicity.rb +111 -0
- data/lib/dust/recipes/etc_hosts.rb +13 -0
- data/lib/dust/recipes/iptables.rb +267 -0
- data/lib/dust/recipes/locale.rb +17 -0
- data/lib/dust/recipes/memory_limit.rb +23 -0
- data/lib/dust/recipes/motd.rb +12 -0
- data/lib/dust/recipes/mysql.rb +49 -0
- data/lib/dust/recipes/nginx.rb +53 -0
- data/lib/dust/recipes/packages.rb +9 -0
- data/lib/dust/recipes/postgres.rb +119 -0
- data/lib/dust/recipes/rc_local.rb +24 -0
- data/lib/dust/recipes/repositories.rb +88 -0
- data/lib/dust/recipes/resolv_conf.rb +42 -0
- data/lib/dust/recipes/ssh_authorized_keys.rb +58 -0
- data/lib/dust/recipes/unattended_upgrades.rb +29 -0
- data/lib/dust/recipes/zabbix_agent.rb +84 -0
- data/lib/dust/server.rb +382 -0
- data/lib/dust/version.rb +3 -0
- metadata +139 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
class SshAuthorizedKeys < Thor
|
4
|
+
desc 'ssh_authorized_keys:deploy', 'configures ssh authorized_keys'
|
5
|
+
def deploy node, ingredients, options
|
6
|
+
template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
|
7
|
+
|
8
|
+
# load users and their ssh keys from yaml file
|
9
|
+
users = YAML.load_file "#{template_path}/users.yaml"
|
10
|
+
|
11
|
+
authorized_keys = {}
|
12
|
+
ingredients.each do |remote_user, ssh_users|
|
13
|
+
::Dust.print_msg "generating authorized_keys for #{remote_user}\n"
|
14
|
+
authorized_keys = ''
|
15
|
+
|
16
|
+
# create the authorized_keys hash for this user
|
17
|
+
ssh_users.each do |ssh_user|
|
18
|
+
::Dust.print_msg "adding user #{users[ssh_user]['name']}", 2
|
19
|
+
users[ssh_user]['keys'].each do |key|
|
20
|
+
authorized_keys += "#{key}"
|
21
|
+
authorized_keys += " #{users[ssh_user]['name']}" if users[ssh_user]['name']
|
22
|
+
authorized_keys += " <#{users[ssh_user]['email']}>" if users[ssh_user]['email']
|
23
|
+
authorized_keys += "\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
::Dust.print_ok
|
27
|
+
end
|
28
|
+
|
29
|
+
# create user, if not existent
|
30
|
+
next unless node.create_user remote_user
|
31
|
+
|
32
|
+
# check and create necessary directories
|
33
|
+
next unless node.mkdir("~#{remote_user}/.ssh")
|
34
|
+
|
35
|
+
# deploy authorized_keys
|
36
|
+
next unless node.write "~#{remote_user}/.ssh/authorized_keys", authorized_keys
|
37
|
+
|
38
|
+
# check permissions
|
39
|
+
node.chown "#{remote_user}:#{remote_user}", "~#{remote_user}/.ssh"
|
40
|
+
node.chmod '0644', "~#{remote_user}/.ssh/authorized_keys"
|
41
|
+
|
42
|
+
|
43
|
+
# TODO: add this option
|
44
|
+
# remove authorized_keys files for all other users
|
45
|
+
if options.cleanup?
|
46
|
+
::Dust.print_msg "deleting other authorized_keys files\n"
|
47
|
+
node.get_system_users(true).each do |user|
|
48
|
+
next if users.keys.include? user
|
49
|
+
if node.file_exists? "~#{user}/.ssh/authorized_keys", true
|
50
|
+
node.rm "~#{user}/.ssh/authorized_keys", 2
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
puts
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class UnattendedUpgrades < Thor
|
2
|
+
desc 'unattended_upgrades:deploy', 'installs and configures automatic system updates for debian and ubuntu'
|
3
|
+
def deploy node, config, options
|
4
|
+
template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
|
5
|
+
|
6
|
+
return unless node.uses_apt?
|
7
|
+
node.install_package 'unattended-upgrades'
|
8
|
+
|
9
|
+
config = {} unless config.class == Hash
|
10
|
+
|
11
|
+
# set defaults for non-set config
|
12
|
+
config['enable'] ||= 1
|
13
|
+
config['update-package-lists'] ||= 1
|
14
|
+
config['unattended-upgrade'] ||= 1
|
15
|
+
config['autocleaninterval'] ||= 1
|
16
|
+
config['verbose'] ||= 0
|
17
|
+
|
18
|
+
# generate configuration file
|
19
|
+
periodic = ''
|
20
|
+
periodic += "APT::Periodic::Enable \"#{config['enable']}\";\n"
|
21
|
+
periodic += "APT::Periodic::Update-Package-Lists \"#{config['update-package-lists']}\";\n"
|
22
|
+
periodic += "APT::Periodic::Unattended-Upgrade \"#{config['unattended-upgrade']}\";\n"
|
23
|
+
periodic += "APT::Periodic::AutocleanInterval \"#{config['autocleaninterval']}\";\n"
|
24
|
+
periodic += "APT::Periodic::Verbose \"#{config['verbose']}\";\n"
|
25
|
+
|
26
|
+
node.write '/etc/apt/apt.conf.d/02periodic', periodic
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
class ZabbixAgent < Thor
|
4
|
+
desc 'zabbix_agent:deploy', 'installs and configures zabbix agent'
|
5
|
+
def deploy node, ingredients, options
|
6
|
+
template_path = "./templates/#{ File.basename(__FILE__).chomp( File.extname(__FILE__) ) }"
|
7
|
+
|
8
|
+
return unless install_zabbix node
|
9
|
+
|
10
|
+
# configure node using erb template
|
11
|
+
template = ERB.new File.read("#{template_path}/zabbix_agentd.conf.erb"), nil, '%<>'
|
12
|
+
::Dust.print_msg 'adjusting and deploying zabbix_agentd.conf'
|
13
|
+
node.write '/etc/zabbix/zabbix_agentd.conf', template.result(binding), true
|
14
|
+
::Dust.print_ok
|
15
|
+
|
16
|
+
# restart using new configuration
|
17
|
+
if node.uses_emerge? true
|
18
|
+
node.autostart_service 'zabbix-agentd'
|
19
|
+
node.restart_service 'zabbix-agentd' if options.restart?
|
20
|
+
else
|
21
|
+
node.autostart_service 'zabbix-agent'
|
22
|
+
node.restart_service 'zabbix-agent' if options.restart?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
# installs zabbix and its dependencies
|
28
|
+
def install_zabbix node
|
29
|
+
|
30
|
+
if node.uses_apt? true
|
31
|
+
return false unless node.install_package('zabbix-agent')
|
32
|
+
|
33
|
+
# debsecan is needed for zabbix checks (security updates)
|
34
|
+
return false unless node.install_package('debsecan')
|
35
|
+
|
36
|
+
elsif node.uses_emerge? true
|
37
|
+
return false unless node.install_package('zabbix', false, 1, "USE=agent")
|
38
|
+
|
39
|
+
# glsa-check (part of gentoolkit) is needed for zabbix checks (security updates)
|
40
|
+
return false unless node.install_package('gentoolkit')
|
41
|
+
|
42
|
+
elsif node.uses_rpm? true
|
43
|
+
return false unless node.install_package('zabbix-agent')
|
44
|
+
|
45
|
+
else
|
46
|
+
::Dust.print_msg 'os not supported'
|
47
|
+
::Dust.print_failed
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
# TODO (not yet finished)
|
55
|
+
desc 'zabbix_agent:postgres', 'configure postgres database for zabbix monitoring'
|
56
|
+
def postgres node, ingredients, options
|
57
|
+
next unless node.uses_emerge?
|
58
|
+
next unless node.package_installed?('postgresql-node')
|
59
|
+
|
60
|
+
::Dust.print_msg 'add zabbix system user to postgres group'
|
61
|
+
::Dust.print_result( node.exec('usermod -a -G postgres zabbix')[:exit_code] )
|
62
|
+
|
63
|
+
::Dust.print_msg 'checking if zabbix user exists in postgres'
|
64
|
+
ret = ::Dust.print_result( node.exec('psql -U postgres -c ' +
|
65
|
+
' "SELECT usename FROM pg_user WHERE usename = \'zabbix\'"' +
|
66
|
+
' postgres |grep -q zabbix')[:exit_code] )
|
67
|
+
|
68
|
+
# if user was not found, create him
|
69
|
+
unless ret
|
70
|
+
::Dust.print_msg 'create zabbix user in postgres', 2
|
71
|
+
::Dust.print_result( node.exec('createuser -U postgres zabbix -RSD')[:exit_code] )
|
72
|
+
end
|
73
|
+
|
74
|
+
# TODO: only GRANT is this is a master
|
75
|
+
::Dust.print_msg 'GRANT zabbix user access to postgres database'
|
76
|
+
::Dust.print_result( node.exec('psql -U postgres -c "GRANT SELECT ON pg_stat_database TO zabbix" postgres')[:exit_code] )
|
77
|
+
|
78
|
+
# reload postgresql
|
79
|
+
node.reload_service('postgresql-9.0')
|
80
|
+
|
81
|
+
node.disconnect
|
82
|
+
puts
|
83
|
+
end
|
84
|
+
end
|
data/lib/dust/server.rb
ADDED
@@ -0,0 +1,382 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'net/ssh'
|
3
|
+
require 'net/scp'
|
4
|
+
require 'net/ssh/proxy/socks5'
|
5
|
+
|
6
|
+
module Dust
|
7
|
+
class Server
|
8
|
+
attr_reader :ssh
|
9
|
+
|
10
|
+
def initialize attr
|
11
|
+
@attr = attr
|
12
|
+
|
13
|
+
# store fully qualified domain name
|
14
|
+
@attr['fqdn'] = @attr['hostname']
|
15
|
+
@attr['fqdn'] += '.' + @attr['domain'] if @attr['domain']
|
16
|
+
|
17
|
+
@attr['user'] ||= 'root'
|
18
|
+
@attr['port'] ||= 22
|
19
|
+
@attr['password'] ||= ''
|
20
|
+
end
|
21
|
+
|
22
|
+
def connect
|
23
|
+
Dust.print_hostname @attr['hostname']
|
24
|
+
begin
|
25
|
+
# connect to proxy if given
|
26
|
+
proxy = @attr.has_key?('proxy') ? Net::SSH::Proxy::SOCKS5.new( @attr['proxy'].split(':')[0],
|
27
|
+
@attr['proxy'].split(':')[1] ) : nil
|
28
|
+
|
29
|
+
@ssh = Net::SSH.start(@attr['fqdn'], @attr['user'],
|
30
|
+
{ :password => @attr['password'],
|
31
|
+
:port => @attr['port'],
|
32
|
+
:proxy => proxy } )
|
33
|
+
rescue Exception
|
34
|
+
error_message = " - coudln't connect to #{@attr['fqdn']}"
|
35
|
+
error_message += " (via socks5 proxy #{@attr['proxy']})" if proxy
|
36
|
+
Dust.print_failed error_message
|
37
|
+
return false
|
38
|
+
end
|
39
|
+
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def disconnect
|
44
|
+
@ssh.close
|
45
|
+
end
|
46
|
+
|
47
|
+
def exec command
|
48
|
+
stdout = ""
|
49
|
+
stderr = ""
|
50
|
+
exit_code = nil
|
51
|
+
exit_signal = nil
|
52
|
+
|
53
|
+
@ssh.open_channel do |channel|
|
54
|
+
channel.exec(command) do |ch, success|
|
55
|
+
unless success
|
56
|
+
abort "FAILED: couldn't execute command (ssh.channel.exec)"
|
57
|
+
end
|
58
|
+
channel.on_data do |ch, data|
|
59
|
+
stdout += data
|
60
|
+
end
|
61
|
+
|
62
|
+
channel.on_extended_data do |ch, type, data|
|
63
|
+
stderr += data
|
64
|
+
end
|
65
|
+
|
66
|
+
channel.on_request("exit-status") do |ch, data|
|
67
|
+
exit_code = data.read_long
|
68
|
+
end
|
69
|
+
|
70
|
+
channel.on_request("exit-signal") do |ch, data|
|
71
|
+
exit_signal = data.read_long
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
@ssh.loop
|
77
|
+
|
78
|
+
{ :stdout => stdout, :stderr => stderr, :exit_code => exit_code, :exit_signal => exit_signal }
|
79
|
+
end
|
80
|
+
|
81
|
+
def write target, text, quiet=false, indent=1
|
82
|
+
Dust.print_msg("deploying #{File.basename(target)}", indent) unless quiet
|
83
|
+
|
84
|
+
# escape $ signs and \ at the end of line
|
85
|
+
text.gsub!('$','\$')
|
86
|
+
text.gsub!(/\\$/, '\\\\\\')
|
87
|
+
|
88
|
+
if exec("cat << EOF > #{target}\n#{text}\nEOF")[:exit_code] != 0
|
89
|
+
return Dust.print_result(false, quiet)
|
90
|
+
end
|
91
|
+
|
92
|
+
Dust.print_ok unless quiet
|
93
|
+
restorecon(target, quiet, indent) # restore SELinux labels
|
94
|
+
end
|
95
|
+
|
96
|
+
def append target, text, quiet=false, indent=1
|
97
|
+
Dust.print_msg("appending to #{File.basename(target)}", indent) unless quiet
|
98
|
+
Dust.print_result( exec("cat << EOF >> #{target}\n#{text}\nEOF")[:exit_code], quiet )
|
99
|
+
end
|
100
|
+
|
101
|
+
def scp source, destination, quiet=false, indent=1
|
102
|
+
Dust.print_msg("deploying #{File.basename(source)}", indent) unless quiet
|
103
|
+
@ssh.scp.upload!(source, destination)
|
104
|
+
Dust.print_result(true, quiet)
|
105
|
+
restorecon(destination, quiet, indent) # restore SELinux labels
|
106
|
+
end
|
107
|
+
|
108
|
+
def symlink source, destination, quiet=false, indent=1
|
109
|
+
Dust.print_msg("symlinking #{File.basename(source)} to '#{destination}'", indent) unless quiet
|
110
|
+
if exec("ln -s #{source} #{destination}")[:exit_code] != 0
|
111
|
+
return Dust.print_result(false, quiet)
|
112
|
+
end
|
113
|
+
|
114
|
+
Dust.print_ok unless quiet
|
115
|
+
restorecon(destination, quiet, indent) # restore SELinux labels
|
116
|
+
end
|
117
|
+
|
118
|
+
def chmod mode, file, quiet=false, indent=1
|
119
|
+
Dust.print_msg("setting mode of #{File.basename(file)} to #{mode}", indent) unless quiet
|
120
|
+
Dust.print_result( exec("chmod -R #{mode} #{file}")[:exit_code], quiet )
|
121
|
+
end
|
122
|
+
|
123
|
+
def chown user, file, quiet=false, indent=1
|
124
|
+
Dust.print_msg("setting owner of #{File.basename(file)} to #{user}", indent) unless quiet
|
125
|
+
Dust.print_result( exec("chown -R #{user} #{file}")[:exit_code], quiet )
|
126
|
+
end
|
127
|
+
|
128
|
+
def rm file, quiet=false, indent=1
|
129
|
+
Dust.print_msg("deleting #{file}", indent) unless quiet
|
130
|
+
Dust.print_result( exec("rm -rf #{file}")[:exit_code], quiet)
|
131
|
+
end
|
132
|
+
|
133
|
+
def mkdir dir, quiet=false, indent=1
|
134
|
+
return true if dir_exists? dir, true
|
135
|
+
Dust.print_msg("creating directory #{dir}", indent) unless quiet
|
136
|
+
if exec("mkdir -p #{dir}")[:exit_code] != 0
|
137
|
+
return Dust.print_result(false, quiet)
|
138
|
+
end
|
139
|
+
|
140
|
+
Dust.print_ok unless quiet
|
141
|
+
restorecon(dir, quiet, indent) # restore SELinux labels
|
142
|
+
end
|
143
|
+
|
144
|
+
# check if restorecon (selinux) is available
|
145
|
+
# if so, run it on "path" recursively
|
146
|
+
def restorecon path, quiet=false, indent=1
|
147
|
+
|
148
|
+
# if restorecon is not installed, just return true
|
149
|
+
ret = exec('which restorecon')
|
150
|
+
return true unless ret[:exit_code] == 0
|
151
|
+
|
152
|
+
Dust.print_msg("restoring selinux labels for #{path}", indent) unless quiet
|
153
|
+
Dust.print_result( exec("#{ret[:stdout].chomp} -R #{path}")[:exit_code], quiet )
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_system_users quiet=false
|
157
|
+
Dust.print_msg("getting all system users", indent) unless quiet
|
158
|
+
ret = exec('getent passwd |cut -d: -f1')
|
159
|
+
Dust.print_result ret[:exit_code]
|
160
|
+
|
161
|
+
users = []
|
162
|
+
ret[:stdout].each do |user|
|
163
|
+
users.push user.chomp
|
164
|
+
end
|
165
|
+
users
|
166
|
+
end
|
167
|
+
|
168
|
+
# checks if one of the packages is installed
|
169
|
+
def package_installed? packages, quiet=false, indent=1
|
170
|
+
packages = [ packages ] if packages.class == String
|
171
|
+
|
172
|
+
Dust.print_msg("checking if #{packages.join(' or ')} is installed", indent) unless quiet
|
173
|
+
|
174
|
+
packages.each do |package|
|
175
|
+
if uses_apt? true
|
176
|
+
return Dust.print_result(true, quiet) unless exec("dpkg -s #{package} |grep 'install ok'")[:stdout].empty?
|
177
|
+
elsif uses_emerge? true
|
178
|
+
return Dust.print_result(true, quiet) unless exec("qlist -I #{package}")[:stdout].empty?
|
179
|
+
elsif uses_rpm? true
|
180
|
+
return Dust.print_result(true, quiet) if exec("rpm -q #{package}")[:exit_code] == 0
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
Dust.print_result(false, quiet)
|
185
|
+
end
|
186
|
+
|
187
|
+
def install_package package, quiet=false, indent=1, env=""
|
188
|
+
return true if package_installed? package, quiet, indent
|
189
|
+
|
190
|
+
Dust.print_msg("installing #{package}", indent + 1) unless quiet
|
191
|
+
if uses_apt? true
|
192
|
+
Dust.print_result exec("DEBIAN_FRONTEND=noninteractive aptitude install -y #{package}")[:exit_code], quiet
|
193
|
+
elsif uses_emerge? true
|
194
|
+
Dust.print_result exec("#{env} emerge #{package}")[:exit_code], quiet
|
195
|
+
elsif uses_rpm? true
|
196
|
+
Dust.print_result exec("yum install -y #{package}; rpm -q #{package}")[:exit_code], quiet
|
197
|
+
else
|
198
|
+
Dust.print_result false, quiet
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def update_repos quiet=false, indent=1
|
203
|
+
Dust.print_msg('updating system repositories', indent) unless quiet
|
204
|
+
if uses_apt? true
|
205
|
+
Dust.print_result exec('DEBIAN_FRONTEND=noninteractive aptitude update')[:exit_code], quiet
|
206
|
+
elsif uses_emerge? true
|
207
|
+
Dust.print_result exec('emerge --sync')[:exit_code], quiet
|
208
|
+
elsif uses_rpm? true
|
209
|
+
Dust.print_result exec('yum check-update')[:exit_code], quiet
|
210
|
+
else
|
211
|
+
Dust.print_result false, quiet
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
def system_update quiet=false, indent=1
|
217
|
+
Dust.print_msg('installing system updates', indent) unless quiet
|
218
|
+
|
219
|
+
if uses_apt? true
|
220
|
+
Dust.print_result exec('DEBIAN_FRONTEND=noninteractive aptitude full-upgrade -y')[:exit_code], quiet
|
221
|
+
elsif uses_emerge? true
|
222
|
+
Dust.print_result exec('emerge -uND @world')[:exit_code], quiet
|
223
|
+
elsif uses_rpm? true
|
224
|
+
Dust.print_result exec('yum upgrade -y')[:exit_code], quiet
|
225
|
+
else
|
226
|
+
Dust.print_result false, quiet
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# determining the system packet manager has to be done without facter
|
231
|
+
# because it's used to find out whether facter is installed / install facter
|
232
|
+
def uses_apt? quiet=false, indent=1
|
233
|
+
Dust.print_msg("determining whether node uses apt", indent) unless quiet
|
234
|
+
Dust.print_result exec('test -e /etc/debian_version')[:exit_code] == 0, quiet
|
235
|
+
end
|
236
|
+
|
237
|
+
def uses_rpm? quiet=false, indent=1
|
238
|
+
Dust.print_msg("determining whether node uses rpm", indent) unless quiet
|
239
|
+
Dust.print_result exec('test -e /etc/redhat-release')[:exit_code] == 0, quiet
|
240
|
+
end
|
241
|
+
|
242
|
+
def uses_emerge? quiet=false, indent=1
|
243
|
+
Dust.print_msg("determining whether node uses emerge", indent) unless quiet
|
244
|
+
Dust.print_result exec('test -e /etc/gentoo-release')[:exit_code] == 0, quiet
|
245
|
+
end
|
246
|
+
|
247
|
+
def is_os? os_list, quiet=false, indent=1
|
248
|
+
Dust.print_msg("checking if this machine runs #{os_list.join(' or ')}", indent) unless quiet
|
249
|
+
collect_facts quiet, indent unless @attr['operatingsystem']
|
250
|
+
|
251
|
+
os_list.each do |os|
|
252
|
+
return Dust.print_result(true, quiet) if @attr['operatingsystem'].downcase == os.downcase
|
253
|
+
end
|
254
|
+
Dust.print_result(false, quiet)
|
255
|
+
end
|
256
|
+
|
257
|
+
def is_debian? quiet=false, indent=1
|
258
|
+
is_os? [ 'debian' ], quiet, indent
|
259
|
+
end
|
260
|
+
|
261
|
+
def is_ubuntu? quiet=false, indent=1
|
262
|
+
is_os? [ 'ubuntu' ], quiet, indent
|
263
|
+
end
|
264
|
+
|
265
|
+
def is_gentoo? quiet=false, indent=1
|
266
|
+
is_os? [ 'gentoo' ], quiet, indent
|
267
|
+
end
|
268
|
+
|
269
|
+
def is_centos? quiet=false, indent=1
|
270
|
+
is_os? [ 'centos' ], quiet, indent
|
271
|
+
end
|
272
|
+
|
273
|
+
def is_scientific? quiet=false, indent=1
|
274
|
+
is_os? [ 'scientific' ], quiet, indent
|
275
|
+
end
|
276
|
+
|
277
|
+
def is_fedora? quiet=false, indent=1
|
278
|
+
is_os? [ 'fedora' ], quiet, indent
|
279
|
+
end
|
280
|
+
|
281
|
+
def is_executable? file, quiet=false, indent=1
|
282
|
+
Dust.print_msg("checking if file #{file} exists and is executeable", indent) unless quiet
|
283
|
+
Dust.print_result( exec("test -x $(which #{file})")[:exit_code], quiet )
|
284
|
+
end
|
285
|
+
|
286
|
+
def file_exists? file, quiet=false, indent=1
|
287
|
+
Dust.print_msg("checking if file #{file} exists", indent) unless quiet
|
288
|
+
Dust.print_result( exec("test -e #{file}")[:exit_code], quiet )
|
289
|
+
end
|
290
|
+
|
291
|
+
def dir_exists? dir, quiet=false, indent=1
|
292
|
+
Dust.print_msg("checking if directory #{dir} exists", indent) unless quiet
|
293
|
+
Dust.print_result( exec("test -d #{dir}")[:exit_code], quiet )
|
294
|
+
end
|
295
|
+
|
296
|
+
def autostart_service service, quiet=false, indent=1
|
297
|
+
Dust.print_msg("autostart #{service} on boot", indent) unless quiet
|
298
|
+
if uses_rpm? true
|
299
|
+
Dust.print_result( exec("chkconfig #{service} on")[:exit_code], quiet )
|
300
|
+
elsif uses_apt? true
|
301
|
+
Dust.print_result( exec("update-rc.d #{service} defaults")[:exit_code], quiet )
|
302
|
+
elsif uses_emerge? true
|
303
|
+
Dust.print_result( exec("rc-update add #{service} default")[:exit_code], quiet )
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def restart_service service, quiet=false, indent=1
|
308
|
+
Dust.print_msg("restarting #{service}", indent) unless quiet
|
309
|
+
Dust.print_result( exec("/etc/init.d/#{service} restart")[:exit_code], quiet )
|
310
|
+
end
|
311
|
+
|
312
|
+
def reload_service service, quiet=false, indent=1
|
313
|
+
Dust.print_msg("reloading #{service}", indent) unless quiet
|
314
|
+
Dust.print_result( exec("/etc/init.d/#{service} reload")[:exit_code], quiet )
|
315
|
+
end
|
316
|
+
|
317
|
+
def qm_list name, quiet=false, indent=1
|
318
|
+
if name
|
319
|
+
Dust.print_msg("looking for a vm with name #{name}", indent) unless quiet
|
320
|
+
ret = exec("qm list |grep #{name}")
|
321
|
+
else
|
322
|
+
Dust.print_msg("looking for vms", indent) unless quiet
|
323
|
+
ret = exec('qm list |grep -v VMID')
|
324
|
+
end
|
325
|
+
|
326
|
+
if Dust.print_result(ret[:exit_code], quiet)
|
327
|
+
return "\t#{ret[:stdout].gsub(/\n/, "\n\t")}"
|
328
|
+
end
|
329
|
+
|
330
|
+
return ''
|
331
|
+
end
|
332
|
+
|
333
|
+
# check whether a user exists on this node
|
334
|
+
def user_exists? user, quiet=false, indent=1
|
335
|
+
Dust.print_msg "checking if user #{user} exists", indent unless quiet
|
336
|
+
Dust.print_result( exec("id #{user}")[:exit_code], quiet )
|
337
|
+
end
|
338
|
+
|
339
|
+
# create a user
|
340
|
+
def create_user user, home=nil, shell=nil, quiet=false, indent=1
|
341
|
+
return true if user_exists? user, quiet, indent
|
342
|
+
|
343
|
+
Dust.print_msg "creating user #{user}", indent + 1 unless quiet
|
344
|
+
cmd = "useradd #{user} -m"
|
345
|
+
cmd += " -d #{home}" if home
|
346
|
+
cmd += " -s #{home}" if shell
|
347
|
+
Dust.print_result( exec(cmd)[:exit_code], quiet )
|
348
|
+
end
|
349
|
+
|
350
|
+
def collect_facts quiet=false, indent=1
|
351
|
+
Dust.print_msg "collecting additional system facts\n" unless quiet
|
352
|
+
|
353
|
+
# collect system facts using puppets facter
|
354
|
+
install_package 'lsb-release', false, 2 if uses_apt?(true) and not package_installed?('lsb-release', true)
|
355
|
+
install_package 'facter', false, 2 unless package_installed? 'facter', true
|
356
|
+
|
357
|
+
Dust.print_msg 'running facter', 2 unless quiet
|
358
|
+
ret = exec 'facter -y'
|
359
|
+
@attr.merge! YAML.load ret[:stdout]
|
360
|
+
Dust.print_result ret[:exit_code], quiet
|
361
|
+
puts unless quiet
|
362
|
+
end
|
363
|
+
|
364
|
+
private
|
365
|
+
|
366
|
+
def method_missing method, *args, &block
|
367
|
+
# make server attributes accessible via server.attribute
|
368
|
+
if @attr[method.to_s]
|
369
|
+
@attr[method.to_s]
|
370
|
+
|
371
|
+
# and as server['attribute']
|
372
|
+
elsif @attr[args.first]
|
373
|
+
@attr[args.first]
|
374
|
+
|
375
|
+
# default to super
|
376
|
+
else
|
377
|
+
super
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
end
|
382
|
+
end
|