Skip to content
This repository was archived by the owner on Nov 9, 2022. It is now read-only.

Commit 67d2d0b

Browse files
Merge pull request #770 from grtjn/703-verified-restart
Fixed #703: restart using rest api, iterate hosts to verify
2 parents 353f2ea + 888a8c3 commit 67d2d0b

File tree

4 files changed

+145
-59
lines changed

4 files changed

+145
-59
lines changed

deploy/lib/Help.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,14 @@ def self.restart
213213
214214
General options:
215215
-v, [--verbose] # Verbose output
216+
--no-verify # Skip verifying the restart
217+
--legacy # Don't use Management REST api
216218
217219
Restart the MarkLogic process in the given environment on each host in the
218220
specified group. If no group is specified, restart the MarkLogic process
219221
on each host in the group to which the target host belongs. Use 'cluster'
220-
to restart all hosts within the cluster to which the target belongs.
222+
to restart all hosts within the cluster to which the target belongs. Restart
223+
is verified by default, Management REST api is used if available.
221224
DOC
222225
end
223226

deploy/lib/MLClient.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,15 @@ def build_request_params(url, verb)
8888
}
8989
end
9090

91-
def go(url, verb, headers = {}, params = nil, body = nil, xcc = false)
91+
def go(url, verb, headers = nil, params = nil, body = nil, xcc = false)
9292
logger.debug(%Q{[#{verb.upcase}]\t#{url}})
9393
password_prompt
9494
request_params = build_request_params(url, verb)
9595
# configure headers
96-
headers.each do |k, v|
97-
request_params[:request][k] = v
96+
if headers
97+
headers.each do |k, v|
98+
request_params[:request][k] = v
99+
end
98100
end
99101

100102
raise ExitException.new("Don't combine params and body. One or the other please") if (params && body)

deploy/lib/server_config.rb

Lines changed: 120 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -533,76 +533,141 @@ def execute_query(query, properties = {})
533533
return r
534534
end
535535

536-
def restart_basic
537-
@ml_username = @properties['ml.bootstrap-user'] || @properties['ml.user']
538-
if @ml_username == @properties['ml.bootstrap-user']
539-
@ml_password = @properties['ml.bootstrap-password']
536+
def restart_group(group = nil, legacy = false)
537+
logger.debug "group: #{group}"
538+
logger.debug "legacy: #{legacy}"
539+
540+
if ! group
541+
# Note:
542+
# Restarting partial cluster is unsafe when working with multiple groups.
543+
# Therefor restart entire cluster by default..
544+
group = "cluster"
545+
end
546+
547+
if group == "cluster"
548+
logger.info "Restarting MarkLogic Server cluster of #{@hostname}"
540549
else
541-
@ml_password = @properties['ml.password']
550+
logger.info "Restarting MarkLogic Server group #{group}"
542551
end
543552

544-
group = nil
545-
ARGV.each do |arg|
546-
# Exclude any argument passed from command line.
547-
if ! arg.match("^-")
548-
group = arg
553+
if @server_version > 7 && !legacy
554+
# MarkLogic 8+, make use of Management REST api and return details of all involved hosts
555+
556+
if group == "cluster"
557+
r = go(%Q{http://#{@properties["ml.server"]}:#{@properties["ml.bootstrap-port"]}/manage/v2?format=json}, "post", {
558+
'Content-Type' => 'application/json'
559+
}, nil, %Q{
560+
{ "operation": "restart-local-cluster" }
561+
})
562+
else
563+
r = go(%Q{http://#{@properties["ml.server"]}:#{@properties["ml.bootstrap-port"]}/manage/v2/groups/#{group}?format=json}, "post", {
564+
'Content-Type' => 'application/json'
565+
}, nil, %Q{
566+
{ "operation": "restart-group" }
567+
})
549568
end
550-
end
551569

552-
if group && group == "cluster"
553-
logger.info "Restarting MarkLogic Server cluster of #{@hostname}"
554-
elsif group
555-
logger.info "Restarting MarkLogic Server group #{group}"
570+
raise ExitException.new(r.body) unless r.code.to_i == 202
571+
572+
return JSON.parse(r.body)['restart']['last-startup']
556573
else
557-
# restarting partial cluster unsafe when working with multiple groups
558-
#logger.info "Restarting MarkLogic Server group of #{@hostname}"
559-
logger.info "Restarting MarkLogic Server cluster of #{@hostname}"
560-
group = "cluster"
574+
# MarkLogic 7- fallback, restart as before, and only verify restart of bootstrap host
575+
576+
old_timestamp = go(%Q{http://#{@properties["ml.server"]}:8001/admin/v1/timestamp}, "get").body
577+
578+
setup = File.read ServerConfig.expand_path("#{@@path}/lib/xquery/setup.xqy")
579+
r = execute_query %Q{#{setup} setup:do-restart("#{group}")}
580+
logger.debug "code: #{r.code.to_i}"
581+
582+
r.body = parse_body(r.body)
583+
logger.info r.body
584+
585+
return [{
586+
'host-id' => @properties["ml.server"],
587+
'value' => old_timestamp
588+
}]
561589
end
562-
logger.debug "this: #{self}"
563-
setup = File.read ServerConfig.expand_path("#{@@path}/lib/xquery/setup.xqy")
564-
r = execute_query %Q{#{setup} setup:do-restart("#{group}")}
565-
logger.debug "code: #{r.code.to_i}"
590+
end
566591

567-
r.body = parse_body(r.body)
568-
logger.info r.body
569-
return true
592+
def get_host_names
593+
r = go(%Q{http://#{@properties["ml.server"]}:8002/manage/v2/hosts?format=json}, "get")
594+
595+
raise ExitException.new(r.body) unless r.code.to_i == 200
596+
597+
names = { @properties["ml.server"] => @properties["ml.server"] } # ml7 fallback
598+
599+
JSON.parse(r.body)['host-default-list']['list-items']['list-item'].each do |host|
600+
names[host['idref']] = host['nameref']
601+
end
602+
603+
return names
570604
end
571605

572-
# implemented verified restart
573606
def restart
574-
verify = find_arg(['--verify'])
575-
if verify==='false'
576-
restart_basic
607+
# Default to verified restart
608+
verify = find_arg(['--no-verify']) == nil && find_arg(['--verify']) != 'false'
609+
# Default to using Management Rest api (if available)
610+
legacy = find_arg(['--legacy']) != nil
611+
612+
logger.debug "verify: #{verify}"
613+
logger.debug "legacy: #{legacy}"
614+
615+
group = next_arg("^[^-]")
616+
617+
@ml_username = @properties['ml.bootstrap-user'] || @properties['ml.user']
618+
if @ml_username == @properties['ml.bootstrap-user']
619+
@ml_password = @properties['ml.bootstrap-password']
577620
else
578-
# defaults to verified restart
579-
old_timestamp = go(%Q{http://#{@properties["ml.server"]}:8001/admin/v1/timestamp}, "get").body
580-
restart_basic
581-
retry_count = 0
582-
retry_max = @properties["ml.verify_retry_max"].to_i
583-
retry_interval = @properties["ml.verify_retry_interval"].to_i
584-
new_timestamp = old_timestamp
585-
while retry_count < retry_max do
586-
begin
587-
new_timestamp = go(%Q{http://#{@properties["ml.server"]}:8001/admin/v1/timestamp}, "get").body
588-
rescue
589-
logger.info 'Verifying restart ...'
590-
logger.debug 'Retry attempt ' + retry_count.to_s + ' failed'
621+
@ml_password = @properties['ml.password']
622+
end
623+
624+
if ! verify
625+
restart_group(group, legacy)
626+
else
627+
host_names = get_host_names()
628+
629+
old_timestamps = restart_group(group, legacy)
630+
631+
# Iterate until all hosts have restarted (or max is reached)
632+
old_timestamps.each do |host|
633+
host_name = host_names[host['host-id']]
634+
old_timestamp = host['value']
635+
636+
print "Verifying restart for #{host_name}"
637+
638+
# Initialize vars for repeated check
639+
retry_count = 0
640+
retry_max = @properties["ml.verify_retry_max"].to_i
641+
retry_interval = [@properties["ml.verify_retry_interval"].to_i, 10].max # 10 sec sleep at least
642+
new_timestamp = old_timestamp
643+
644+
while retry_count < retry_max do
645+
begin
646+
new_timestamp = go(%Q{http://#{host_name}:8001/admin/v1/timestamp}, "get").body
647+
rescue
648+
logger.debug 'Retry attempt ' + retry_count.to_s + ' failed'
649+
end
650+
651+
if new_timestamp != old_timestamp
652+
# Indicates that restart is confirmed successful
653+
break
654+
end
655+
656+
# Retry..
657+
print ".."
658+
sleep retry_interval
659+
retry_count += 1
591660
end
592-
if new_timestamp != old_timestamp
593-
# indicates that restart is confirmed successful
594-
break
661+
662+
if retry_max < 1
663+
puts ": SKIPPED"
664+
elsif new_timestamp == old_timestamp
665+
puts ": FAILED"
666+
else
667+
puts ": OK"
595668
end
596-
logger.debug "Verifying restart..."
597-
sleep retry_interval
598-
retry_count += 1
599-
end
600-
if new_timestamp == old_timestamp
601-
logger.warn "Could not verify restart"
602-
else
603-
logger.info 'Verified restart.'
604-
logger.debug "Verified restart new #{new_timestamp} old #{old_timestamp}"
605669
end
670+
606671
end
607672
end
608673

deploy/lib/util.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,22 @@ def find_arg(args = [])
3636
nil
3737
end
3838

39+
def next_arg(match)
40+
ARGV.each do |arg|
41+
# Exclude any argument passed from command line.
42+
if arg.match(match)
43+
44+
# Remove group from arguments list
45+
index = ARGV.index(arg)
46+
ARGV.slice!(index)
47+
48+
# Bail out on first valid arg
49+
return arg
50+
end
51+
end
52+
nil
53+
end
54+
3955
def load_prop_from_args(props)
4056
ARGV.each do |a|
4157
if a.match(/(^--)(ml\..*)(=)(.*)/)

0 commit comments

Comments
 (0)