omnibus-ctl 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +85 -0
- data/bin/omnibus-ctl +33 -0
- data/lib/omnibus-ctl.rb +559 -0
- data/lib/omnibus-ctl/version.rb +5 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3f727fad81d619b5de76e830757918590df8b636
|
4
|
+
data.tar.gz: 2a606b930145058c04f31a36f14ff4f32f1d1449
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ed89feaa9a4cfedb22f06640efd44644f1908cc6c254ba19185e41e144d722006855cb57c451c86e293448a3269ecae36acf725948cab7f83539df0e01aec4f7
|
7
|
+
data.tar.gz: 4627bd21c3569788abdca489e4d94096d847861fbfee83f35eb9cbbaeb67e29c4859dd5e67507ad8e94fe9d4f849d4ccee3a805aac8ab9ff6830263b37c57a21
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
## omnibus-ctl
|
2
|
+
|
3
|
+
omnibus-ctl provides service control and configuration for omnibus packages.
|
4
|
+
|
5
|
+
Not much to see here yet.
|
6
|
+
|
7
|
+
### Run the Tests!
|
8
|
+
|
9
|
+
There are tests in this repo that should be run before merging to master in the `spec` directory.
|
10
|
+
|
11
|
+
To run them, first install rspec via bundler:
|
12
|
+
|
13
|
+
```
|
14
|
+
bundle install --binstubs
|
15
|
+
```
|
16
|
+
|
17
|
+
Then run the tests:
|
18
|
+
|
19
|
+
```
|
20
|
+
./bin/rspec spec/
|
21
|
+
```
|
22
|
+
|
23
|
+
### Framework API
|
24
|
+
|
25
|
+
There are two main functions you will use in your `*-ctl` project to add commands.
|
26
|
+
|
27
|
+
#### add_command_under_category(string, string, string, int, ruby_block)
|
28
|
+
|
29
|
+
This method will add a new command to your ctl under a category, useful for grouping similar commands together logically in help output.
|
30
|
+
|
31
|
+
Input arguments:
|
32
|
+
|
33
|
+
1. Name of the command.
|
34
|
+
2. Category of the command. It should be string consisting of only characters and "-". If the category does not exist, it will be added. Default categories are "general" and "service-management" (if the latter is enabled).
|
35
|
+
3. Description. This will be outputted below the command name when the help command is run.
|
36
|
+
4. Arity. TODO: Due to current bug, this must be 2, I believe. We should fix this.
|
37
|
+
5. Ruby block. Ruby code to be executed when your command is run (arguments to that command will be passed into the block).
|
38
|
+
|
39
|
+
#### add_command(string, string, int, ruby_block)
|
40
|
+
|
41
|
+
This method will add a new command to your ctl without a category. It will be displayed above all categories when the help command is called.
|
42
|
+
|
43
|
+
Input arguments are the same as `add_command_under_category` except 2 doesn't exist.
|
44
|
+
|
45
|
+
#### Sample Output
|
46
|
+
|
47
|
+
```
|
48
|
+
# sample-ctl help
|
49
|
+
/opt/opscode/embedded/bin/sample-ctl: command (subcommand)
|
50
|
+
command-without-category
|
51
|
+
Here is an insightful description for the above command, added via add_command.
|
52
|
+
another-command-without-category
|
53
|
+
Yet another description.
|
54
|
+
Some Category Of Commands:
|
55
|
+
command-with-category
|
56
|
+
Exciting description of command added via add_command_under_category.
|
57
|
+
better-command-with-category
|
58
|
+
You get the idea.
|
59
|
+
Another Category:
|
60
|
+
command-with-better-category
|
61
|
+
I'm not just going to copy-pasta above example descriptions.
|
62
|
+
better-command-with-better-category
|
63
|
+
I'm running out of ideas.
|
64
|
+
```
|
65
|
+
|
66
|
+
If you only use `add_command_under_category` to add your custom commands, everything will be outputted under a category.
|
67
|
+
|
68
|
+
### Licensing
|
69
|
+
|
70
|
+
See the LICENSE file for details.
|
71
|
+
|
72
|
+
Copyright: Copyright (c) 2012 Opscode, Inc.
|
73
|
+
License: Apache License, Version 2.0
|
74
|
+
|
75
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
76
|
+
you may not use this file except in compliance with the License.
|
77
|
+
You may obtain a copy of the License at
|
78
|
+
|
79
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
80
|
+
|
81
|
+
Unless required by applicable law or agreed to in writing, software
|
82
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
83
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
84
|
+
See the License for the specific language governing permissions and
|
85
|
+
limitations under the License.
|
data/bin/omnibus-ctl
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
4
|
+
# Copyright:: Copyright (c) 2011 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'omnibus-ctl'
|
21
|
+
|
22
|
+
# service name: ARGV[0]
|
23
|
+
# additional modules: ARGV[1]
|
24
|
+
# command: ARGV[2]
|
25
|
+
# service: ARGV[3]
|
26
|
+
# options: ARGV[4..]
|
27
|
+
|
28
|
+
ctl = Omnibus::Ctl.new(ARGV[0])
|
29
|
+
ctl.load_files(ARGV[1])
|
30
|
+
arguments = ARGV[2..-1] # Get the rest of the command line arguments
|
31
|
+
ctl.run(arguments)
|
32
|
+
exit 0
|
33
|
+
|
data/lib/omnibus-ctl.rb
ADDED
@@ -0,0 +1,559 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require "omnibus-ctl/version"
|
19
|
+
require 'json'
|
20
|
+
require 'fileutils'
|
21
|
+
|
22
|
+
module Omnibus
|
23
|
+
class Ctl
|
24
|
+
|
25
|
+
File::umask(022)
|
26
|
+
|
27
|
+
SV_COMMAND_NAMES = %w[status up down once pause cont hup alarm interrupt quit
|
28
|
+
term kill start stop restart shutdown force-stop
|
29
|
+
force-reload force-restart force-shutdown check]
|
30
|
+
|
31
|
+
attr_accessor :name, :display_name, :log_exclude, :base_path, :sv_path,
|
32
|
+
:service_path, :etc_path, :data_path, :log_path, :command_map, :category_command_map,
|
33
|
+
:fh_output, :kill_users, :verbose, :log_path_exclude
|
34
|
+
|
35
|
+
def initialize(name, service_commands=true)
|
36
|
+
@name = name
|
37
|
+
@service_commands = service_commands
|
38
|
+
@display_name = name
|
39
|
+
@base_path = "/opt/#{name}"
|
40
|
+
@sv_path = File.join(@base_path, "sv")
|
41
|
+
@service_path = File.join(@base_path, "service")
|
42
|
+
@log_path = "/var/log/#{name}"
|
43
|
+
@data_path = "/var/opt/#{name}"
|
44
|
+
@etc_path = "/etc/#{name}"
|
45
|
+
@log_exclude = '(config|lock|@|gzip|tgz|gz)'
|
46
|
+
@log_path_exclude = ['*/sasl/*']
|
47
|
+
@fh_output = STDOUT
|
48
|
+
@kill_users = []
|
49
|
+
@verbose = false
|
50
|
+
# backwards compat command map that does not have categories
|
51
|
+
@command_map = { }
|
52
|
+
|
53
|
+
# categoired commands that we want by default
|
54
|
+
@category_command_map = {
|
55
|
+
"general" => {
|
56
|
+
"show-config" => {
|
57
|
+
:desc => "Show the configuration that would be generated by reconfigure.",
|
58
|
+
:arity => 1
|
59
|
+
},
|
60
|
+
"reconfigure" => {
|
61
|
+
:desc => "Reconfigure the application.",
|
62
|
+
:arity => 1
|
63
|
+
},
|
64
|
+
"cleanse" => {
|
65
|
+
:desc => "Delete *all* #{display_name} data, and start from scratch.",
|
66
|
+
:arity => 2
|
67
|
+
},
|
68
|
+
"uninstall" => {
|
69
|
+
:arity => 1,
|
70
|
+
:desc => "Kill all processes and uninstall the process supervisor (data will be preserved)."
|
71
|
+
},
|
72
|
+
"help" => {
|
73
|
+
:arity => 1,
|
74
|
+
:desc => "Print this help message."
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
service_command_map = {
|
79
|
+
"service-management" => {
|
80
|
+
"service-list" => {
|
81
|
+
:arity => 1,
|
82
|
+
:desc => "List all the services (enabled services appear with a *.)"
|
83
|
+
},
|
84
|
+
"status" => {
|
85
|
+
:desc => "Show the status of all the services.",
|
86
|
+
:arity => 2
|
87
|
+
},
|
88
|
+
"tail" => {
|
89
|
+
:desc => "Watch the service logs of all enabled services.",
|
90
|
+
:arity => 2
|
91
|
+
},
|
92
|
+
"start" => {
|
93
|
+
:desc => "Start services if they are down, and restart them if they stop.",
|
94
|
+
:arity => 2
|
95
|
+
},
|
96
|
+
"stop" => {
|
97
|
+
:desc => "Stop the services, and do not restart them.",
|
98
|
+
:arity => 2
|
99
|
+
},
|
100
|
+
"restart" => {
|
101
|
+
:desc => "Stop the services if they are running, then start them again.",
|
102
|
+
:arity => 2
|
103
|
+
},
|
104
|
+
"once" => {
|
105
|
+
:desc => "Start the services if they are down. Do not restart them if they stop.",
|
106
|
+
:arity => 2
|
107
|
+
},
|
108
|
+
"hup" => {
|
109
|
+
:desc => "Send the services a HUP.",
|
110
|
+
:arity => 2
|
111
|
+
},
|
112
|
+
"term" => {
|
113
|
+
:desc => "Send the services a TERM.",
|
114
|
+
:arity => 2
|
115
|
+
},
|
116
|
+
"int" => {
|
117
|
+
:desc => "Send the services an INT.",
|
118
|
+
:arity => 2
|
119
|
+
},
|
120
|
+
"kill" => {
|
121
|
+
:desc => "Send the services a KILL.",
|
122
|
+
:arity => 2
|
123
|
+
},
|
124
|
+
"graceful-kill" => {
|
125
|
+
:desc => "Attempt a graceful stop, then SIGKILL the entire process group.",
|
126
|
+
:arity => 2
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
@category_command_map.merge!(service_command_map) if service_commands?
|
131
|
+
end
|
132
|
+
|
133
|
+
SV_COMMAND_NAMES.each do |sv_cmd|
|
134
|
+
method_name = sv_cmd.gsub(/-/, "_")
|
135
|
+
Omnibus::Ctl.class_eval <<-EOH
|
136
|
+
def #{method_name}(*args)
|
137
|
+
run_sv_command(*args)
|
138
|
+
end
|
139
|
+
EOH
|
140
|
+
end
|
141
|
+
|
142
|
+
# merges category_command_map and command_map,
|
143
|
+
# removing categories
|
144
|
+
def get_all_commands_hash
|
145
|
+
without_categories = {}
|
146
|
+
category_command_map.each do |category, commands|
|
147
|
+
without_categories.merge!(commands)
|
148
|
+
end
|
149
|
+
command_map.merge(without_categories)
|
150
|
+
end
|
151
|
+
|
152
|
+
def service_commands?
|
153
|
+
@service_commands
|
154
|
+
end
|
155
|
+
|
156
|
+
def load_files(path)
|
157
|
+
Dir["#{path}/*.rb"].each do |file|
|
158
|
+
eval(IO.read(file))
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def add_command(name, description, arity=1, &block)
|
163
|
+
@command_map[name] = { :desc => description, :arity => arity }
|
164
|
+
metaclass = class << self; self; end
|
165
|
+
# Ruby does not like dashes in method names
|
166
|
+
method_name = name.gsub(/-/, "_")
|
167
|
+
metaclass.send(:define_method, method_name.to_sym) { |*args| block.call(*args) }
|
168
|
+
end
|
169
|
+
|
170
|
+
def add_command_under_category(name, category, description, arity=1, &block)
|
171
|
+
# add new category if it doesn't exist
|
172
|
+
@category_command_map[category] = {} unless @category_command_map.has_key?(category)
|
173
|
+
@category_command_map[category][name] = { :desc => description, :arity => arity }
|
174
|
+
metaclass = class << self; self; end
|
175
|
+
# Ruby does not like dashes in method names
|
176
|
+
method_name = name.gsub(/-/, "_")
|
177
|
+
metaclass.send(:define_method, method_name.to_sym) { |*args| block.call(*args) }
|
178
|
+
end
|
179
|
+
|
180
|
+
def exit!(error_code)
|
181
|
+
exit error_code
|
182
|
+
end
|
183
|
+
|
184
|
+
def log(msg)
|
185
|
+
fh_output.puts msg
|
186
|
+
end
|
187
|
+
|
188
|
+
def get_pgrp_from_pid(pid)
|
189
|
+
ps=`which ps`.chomp
|
190
|
+
`#{ps} -p #{pid} -o pgrp=`.chomp
|
191
|
+
end
|
192
|
+
|
193
|
+
def get_pids_from_pgrp(pgrp)
|
194
|
+
pgrep=`which pgrep`.chomp
|
195
|
+
`#{pgrep} -g #{pgrp}`.split(/\n/).join(" ")
|
196
|
+
end
|
197
|
+
|
198
|
+
def sigkill_pgrp(pgrp)
|
199
|
+
pkill=`which pkill`.chomp
|
200
|
+
run_command("#{pkill} -9 -g #{pgrp}")
|
201
|
+
end
|
202
|
+
|
203
|
+
def run_command(command)
|
204
|
+
system(command)
|
205
|
+
$?
|
206
|
+
end
|
207
|
+
|
208
|
+
def service_list(*args)
|
209
|
+
get_all_services.each do |service_name|
|
210
|
+
print "#{service_name}"
|
211
|
+
print "*" if service_enabled?(service_name)
|
212
|
+
print "\n"
|
213
|
+
end
|
214
|
+
exit! 0
|
215
|
+
end
|
216
|
+
|
217
|
+
def cleanup_procs_and_nuke(filestr)
|
218
|
+
begin
|
219
|
+
run_sv_command("stop")
|
220
|
+
rescue SystemExit
|
221
|
+
end
|
222
|
+
|
223
|
+
FileUtils.rm_f("/etc/init/#{name}-runsvdir.conf") if File.exists?("/etc/init/#{name}-runsvdir.conf")
|
224
|
+
run_command("egrep -v '#{base_path}/embedded/bin/runsvdir-start' /etc/inittab > /etc/inittab.new && mv /etc/inittab.new /etc/inittab") if File.exists?("/etc/inittab")
|
225
|
+
run_command("kill -1 1")
|
226
|
+
|
227
|
+
backup_dir = Time.now.strftime("/root/#{name}-cleanse-%FT%R")
|
228
|
+
FileUtils.mkdir_p("/root") unless File.exists?("/root")
|
229
|
+
FileUtils.rm_rf(backup_dir)
|
230
|
+
FileUtils.cp_r(etc_path, backup_dir) if File.exists?(etc_path)
|
231
|
+
run_command("rm -rf #{filestr}")
|
232
|
+
|
233
|
+
begin
|
234
|
+
graceful_kill
|
235
|
+
rescue SystemExit
|
236
|
+
end
|
237
|
+
|
238
|
+
run_command("pkill -HUP -u #{kill_users.join(',')}") if kill_users.length > 0
|
239
|
+
run_command("pkill -HUP -f 'runsvdir -P #{service_path}'")
|
240
|
+
sleep 3
|
241
|
+
run_command("pkill -TERM -u #{kill_users.join(',')}") if kill_users.length > 0
|
242
|
+
run_command("pkill -TERM -f 'runsvdir -P #{service_path}'")
|
243
|
+
sleep 3
|
244
|
+
run_command("pkill -KILL -u #{kill_users.join(',')}") if kill_users.length > 0
|
245
|
+
run_command("pkill -KILL -f 'runsvdir -P #{service_path}'")
|
246
|
+
|
247
|
+
get_all_services.each do |die_daemon_die|
|
248
|
+
run_command("pkill -KILL -f 'runsv #{die_daemon_die}'")
|
249
|
+
end
|
250
|
+
|
251
|
+
log "Your config files have been backed up to #{backup_dir}."
|
252
|
+
exit! 0
|
253
|
+
end
|
254
|
+
|
255
|
+
def uninstall(*args)
|
256
|
+
cleanup_procs_and_nuke("/tmp/opt")
|
257
|
+
end
|
258
|
+
|
259
|
+
def cleanse(*args)
|
260
|
+
log "This will delete *all* configuration, log, and variable data associated with this application.\n\n*** You have 60 seconds to hit CTRL-C ***\n\n"
|
261
|
+
unless args[1] == "yes"
|
262
|
+
sleep 60
|
263
|
+
end
|
264
|
+
cleanup_procs_and_nuke("#{service_path}/* /tmp/opt #{data_path} #{etc_path} #{log_path}")
|
265
|
+
end
|
266
|
+
|
267
|
+
def get_all_services_files
|
268
|
+
Dir[File.join(sv_path, '*')]
|
269
|
+
end
|
270
|
+
|
271
|
+
def get_all_services
|
272
|
+
get_all_services_files.map { |f| File.basename(f) }.sort
|
273
|
+
end
|
274
|
+
|
275
|
+
def service_enabled?(service_name)
|
276
|
+
File.symlink?("#{service_path}/#{service_name}")
|
277
|
+
end
|
278
|
+
|
279
|
+
def run_sv_command(sv_cmd, service=nil)
|
280
|
+
exit_status = 0
|
281
|
+
if service
|
282
|
+
exit_status += run_sv_command_for_service(sv_cmd, service)
|
283
|
+
else
|
284
|
+
get_all_services.each do |service_name|
|
285
|
+
exit_status += run_sv_command_for_service(sv_cmd, service_name) if global_service_command_permitted(sv_cmd, service_name)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
exit! exit_status
|
289
|
+
end
|
290
|
+
|
291
|
+
# run an sv command for a specific service name
|
292
|
+
def run_sv_command_for_service(sv_cmd, service_name)
|
293
|
+
if service_enabled?(service_name)
|
294
|
+
status = run_command("#{base_path}/init/#{service_name} #{sv_cmd}")
|
295
|
+
return status.exitstatus
|
296
|
+
else
|
297
|
+
log "#{service_name} disabled" if sv_cmd == "status" && verbose
|
298
|
+
return 0
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# if we're running a global service command (like p-c-c status)
|
303
|
+
# across all of the services, there are certain cases where we
|
304
|
+
# want to prevent services files that exist in the service
|
305
|
+
# directory from being activated. This method is the logic that
|
306
|
+
# blocks those services
|
307
|
+
def global_service_command_permitted(sv_cmd, service_name)
|
308
|
+
# For services that have been removed, we only want to
|
309
|
+
# them to respond to the stop command. They should not show
|
310
|
+
# up in status, and they should not be started.
|
311
|
+
if removed_services.include?(service_name)
|
312
|
+
return sv_cmd == "stop"
|
313
|
+
end
|
314
|
+
|
315
|
+
# For keepalived, we only want it to respond to the status
|
316
|
+
# command when running global service commands like p-c-c start
|
317
|
+
# and p-c-c stop
|
318
|
+
if service_name == "keepalived"
|
319
|
+
return sv_cmd == "status"
|
320
|
+
end
|
321
|
+
|
322
|
+
# If c-s-c status is called, check to see if the service
|
323
|
+
# is hidden supposed to be hidden from the status results
|
324
|
+
# (mover for example should be hidden).
|
325
|
+
if sv_cmd == "status"
|
326
|
+
return !(hidden_services.include?(service_name))
|
327
|
+
end
|
328
|
+
|
329
|
+
# All other services respond normally to p-c-c * commands
|
330
|
+
return true
|
331
|
+
end
|
332
|
+
|
333
|
+
# removed services are configured via the attributes file in
|
334
|
+
# the main omnibus cookbook
|
335
|
+
def removed_services
|
336
|
+
# in the case that there is no running_config (the config file does
|
337
|
+
# not exist), we know that this will be a new server, and we don't
|
338
|
+
# have to worry about pre-upgrade services hanging around. We can safely
|
339
|
+
# return an empty array when running_config is nil
|
340
|
+
if (cfg = running_config)
|
341
|
+
key = package_name.gsub(/-/, '_')
|
342
|
+
cfg[key]["removed_services"] || []
|
343
|
+
else
|
344
|
+
[]
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
# hidden services are configured via the attributes file in
|
349
|
+
# the main omnibus cookbook
|
350
|
+
#
|
351
|
+
# hidden services are services that we do not want to show up in
|
352
|
+
# c-s-c status.
|
353
|
+
def hidden_services
|
354
|
+
# in the case that there is no running_config (the config file does
|
355
|
+
# not exist), we don't want to return nil, just return an empty array.
|
356
|
+
# worse result with doing that is services that we don't want to show up in
|
357
|
+
# c-s-c status will show up.
|
358
|
+
if (cfg = running_config)
|
359
|
+
key = package_name.gsub(/-/, '_')
|
360
|
+
cfg[key]["hidden_services"] || []
|
361
|
+
else
|
362
|
+
[]
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
# translate the name from the config to the package name.
|
367
|
+
# this is a special case for the private-chef package because
|
368
|
+
# it is configured to use the name and directory structure of
|
369
|
+
# 'opscode', not 'private-chef'
|
370
|
+
def package_name
|
371
|
+
case @name
|
372
|
+
when "opscode"
|
373
|
+
"private-chef"
|
374
|
+
else
|
375
|
+
@name
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
# returns nil when chef-server-running.json does not exist
|
380
|
+
def running_config
|
381
|
+
@running_config ||= begin
|
382
|
+
if File.exists?("#{etc_path}/chef-server-running.json")
|
383
|
+
JSON.parse(File.read("#{etc_path}/chef-server-running.json"))
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
def show_config(*args)
|
389
|
+
status = run_command("#{base_path}/embedded/bin/chef-client -z -c #{base_path}/embedded/cookbooks/solo.rb -j #{base_path}/embedded/cookbooks/show-config.json -l fatal")
|
390
|
+
if status.success?
|
391
|
+
exit! 0
|
392
|
+
else
|
393
|
+
exit! 1
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
def reconfigure(exit_on_success=true)
|
398
|
+
status = run_command("#{base_path}/embedded/bin/chef-client -z -c #{base_path}/embedded/cookbooks/solo.rb -j #{base_path}/embedded/cookbooks/dna.json")
|
399
|
+
if status.success?
|
400
|
+
log "#{display_name} Reconfigured!"
|
401
|
+
exit! 0 if exit_on_success
|
402
|
+
else
|
403
|
+
exit! 1
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
def tail(*args)
|
408
|
+
# find /var/log -type f -not -path '*/sasl/*' | grep -E -v '(lock|@|tgz|gzip)' | xargs tail --follow=name --retry
|
409
|
+
command = "find #{log_path}"
|
410
|
+
command << "/#{args[1]}" if args[1]
|
411
|
+
command << ' -type f'
|
412
|
+
command << log_path_exclude.map { |path| " -not -path #{path}" }.join(' ')
|
413
|
+
command << " | grep -E -v '#{log_exclude}' | xargs tail --follow=name --retry"
|
414
|
+
|
415
|
+
system(command)
|
416
|
+
end
|
417
|
+
|
418
|
+
def is_integer?(string)
|
419
|
+
return true if Integer(string) rescue false
|
420
|
+
end
|
421
|
+
|
422
|
+
def graceful_kill(*args)
|
423
|
+
service = args[1]
|
424
|
+
exit_status = 0
|
425
|
+
get_all_services.each do |service_name|
|
426
|
+
next if !service.nil? && service_name != service
|
427
|
+
if service_enabled?(service_name)
|
428
|
+
pidfile="#{sv_path}/#{service_name}/supervise/pid"
|
429
|
+
pid=File.read(pidfile).chomp if File.exists?(pidfile)
|
430
|
+
if pid.nil? || !is_integer?(pid)
|
431
|
+
log "could not find #{service_name} runit pidfile (service already stopped?), cannot attempt SIGKILL..."
|
432
|
+
status = run_command("#{base_path}/init/#{service_name} stop")
|
433
|
+
exit_status = status.exitstatus if exit_status == 0 && !status.success?
|
434
|
+
next
|
435
|
+
end
|
436
|
+
pgrp=get_pgrp_from_pid(pid)
|
437
|
+
if pgrp.nil? || !is_integer?(pgrp)
|
438
|
+
log "could not find pgrp of pid #{pid} (not running?), cannot attempt SIGKILL..."
|
439
|
+
status = run_command("#{base_path}/init/#{service_name} stop")
|
440
|
+
exit_status = status.exitstatus if exit_status == 0 && !status.success?
|
441
|
+
next
|
442
|
+
end
|
443
|
+
run_command("#{base_path}/init/#{service_name} stop")
|
444
|
+
pids=get_pids_from_pgrp(pgrp)
|
445
|
+
if !pids.empty?
|
446
|
+
log "found stuck pids still running in process group: #{pids}, sending SIGKILL" unless pids.empty?
|
447
|
+
sigkill_pgrp(pgrp)
|
448
|
+
end
|
449
|
+
else
|
450
|
+
log "#{service_name} disabled, not stopping"
|
451
|
+
exit_status = 1
|
452
|
+
end
|
453
|
+
end
|
454
|
+
exit! exit_status
|
455
|
+
end
|
456
|
+
|
457
|
+
def help(*args)
|
458
|
+
log "#{$0}: command (subcommand)\n"
|
459
|
+
command_map.keys.sort.each do |command|
|
460
|
+
log command
|
461
|
+
log " #{command_map[command][:desc]}"
|
462
|
+
end
|
463
|
+
category_command_map.each do |category, commands|
|
464
|
+
# Remove "-" and replace with spaces in category and capalize for output
|
465
|
+
category_string = category.gsub("-", " ").split.map(&:capitalize).join(' ')
|
466
|
+
log "#{category_string} Commands:\n"
|
467
|
+
|
468
|
+
# Print each command in this category
|
469
|
+
commands.keys.sort.each do |command|
|
470
|
+
log " #{command}"
|
471
|
+
log " #{commands[command][:desc]}"
|
472
|
+
end
|
473
|
+
end
|
474
|
+
exit! 1
|
475
|
+
end
|
476
|
+
|
477
|
+
# Set options. Silently ignore bad options.
|
478
|
+
# This allows the test subcommand to pass on pedant options
|
479
|
+
def parse_options!(args)
|
480
|
+
args.each do |option|
|
481
|
+
case option
|
482
|
+
when "--verbose", "-v"
|
483
|
+
@verbose = true
|
484
|
+
end
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
# If it begins with a '-', it is an option.
|
489
|
+
def is_option?(arg)
|
490
|
+
arg && arg[0] == '-'
|
491
|
+
end
|
492
|
+
|
493
|
+
# retrieves the commmand from either the command_map
|
494
|
+
# or the category_command_map, if the command is not found
|
495
|
+
# return nil
|
496
|
+
def retrieve_command(command_to_run)
|
497
|
+
if command_map.has_key?(command_to_run)
|
498
|
+
command_map[command_to_run]
|
499
|
+
else
|
500
|
+
command = nil
|
501
|
+
category_command_map.each do |category, commands|
|
502
|
+
command = commands[command_to_run] if commands.has_key?(command_to_run)
|
503
|
+
end
|
504
|
+
# return the command, or nil if it wasn't found
|
505
|
+
command
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
def run(args)
|
510
|
+
# Ensure Omnibus related binaries are in the PATH
|
511
|
+
ENV["PATH"] = [File.join(base_path, "bin"),
|
512
|
+
File.join(base_path, "embedded","bin"),
|
513
|
+
ENV['PATH']].join(":")
|
514
|
+
|
515
|
+
command_to_run = args[0]
|
516
|
+
|
517
|
+
# This piece of code checks if the argument is an option. If it is,
|
518
|
+
# then it sets service to nil and adds the argument into the options
|
519
|
+
# argument. This is ugly. A better solution is having a proper parser.
|
520
|
+
# But if we are going to implement a proper parser, we might as well
|
521
|
+
# port this to Thor rather than reinventing Thor. For now, this preserves
|
522
|
+
# the behavior to complain and exit with an error if one attempts to invoke
|
523
|
+
# a pcc command that does not accept an argument. Like "help".
|
524
|
+
options = args[2..-1] || []
|
525
|
+
if is_option?(args[1])
|
526
|
+
options.unshift(args[1])
|
527
|
+
service = nil
|
528
|
+
else
|
529
|
+
service = args[1]
|
530
|
+
end
|
531
|
+
|
532
|
+
# returns either hash content of comamnd or nil
|
533
|
+
command = retrieve_command(command_to_run)
|
534
|
+
|
535
|
+
if command.nil?
|
536
|
+
log "I don't know that command."
|
537
|
+
if args.length == 2
|
538
|
+
log "Did you mean: #{$0} #{service} #{command_to_run}?"
|
539
|
+
end
|
540
|
+
help
|
541
|
+
end
|
542
|
+
|
543
|
+
if args.length > 1 && command[:arity] != 2
|
544
|
+
log "The command #{command_to_run} does not accept any arguments"
|
545
|
+
exit! 2
|
546
|
+
end
|
547
|
+
|
548
|
+
parse_options! options
|
549
|
+
|
550
|
+
method_to_call = command_to_run.gsub(/-/, '_')
|
551
|
+
# Filter args to just command and service. If you are loading
|
552
|
+
# custom commands and need access to the command line argument,
|
553
|
+
# use ARGV directly.
|
554
|
+
actual_args = [command_to_run, service].reject(&:nil?)
|
555
|
+
self.send(method_to_call.to_sym, *actual_args)
|
556
|
+
end
|
557
|
+
|
558
|
+
end
|
559
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: omnibus-ctl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Opscode, Inc.
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec_junit_formatter
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Provides command line control for omnibus pakcages, rarely used as a
|
42
|
+
gem
|
43
|
+
email:
|
44
|
+
- legal@opscode.com
|
45
|
+
executables:
|
46
|
+
- omnibus-ctl
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- README.md
|
51
|
+
- bin/omnibus-ctl
|
52
|
+
- lib/omnibus-ctl.rb
|
53
|
+
- lib/omnibus-ctl/version.rb
|
54
|
+
homepage: http://github.com/opscode/omnibus-ctl
|
55
|
+
licenses: []
|
56
|
+
metadata: {}
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 2.2.2
|
74
|
+
signing_key:
|
75
|
+
specification_version: 4
|
76
|
+
summary: Provides command line control for omnibus packages
|
77
|
+
test_files: []
|
78
|
+
has_rdoc:
|