gitchefsync 0.6.1
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.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +2 -0
- data/README.md +150 -0
- data/Rakefile +2 -0
- data/bin/gitchefsync +18 -0
- data/build.sh +20 -0
- data/gitchefsync.gemspec +29 -0
- data/lib/gitchefsync/audit.rb +219 -0
- data/lib/gitchefsync/common.rb +178 -0
- data/lib/gitchefsync/config.rb +88 -0
- data/lib/gitchefsync/env_sync.rb +339 -0
- data/lib/gitchefsync/errors.rb +35 -0
- data/lib/gitchefsync/git_util.rb +102 -0
- data/lib/gitchefsync/io_util.rb +83 -0
- data/lib/gitchefsync/knife_util.rb +209 -0
- data/lib/gitchefsync/log.rb +46 -0
- data/lib/gitchefsync/notify.rb +74 -0
- data/lib/gitchefsync/opts.rb +64 -0
- data/lib/gitchefsync/schedule.rb +161 -0
- data/lib/gitchefsync/version.rb +3 -0
- data/lib/gitchefsync.rb +516 -0
- data/spec/README.md +0 -0
- data/spec/config-nogitgroup.json +13 -0
- data/spec/gitchefsync_spec.rb +89 -0
- data/spec/integration.rb +68 -0
- data/spec/sync-config.json +13 -0
- metadata +120 -0
@@ -0,0 +1,209 @@
|
|
1
|
+
#helper file for parsing knife commands
|
2
|
+
#this may get refactored
|
3
|
+
|
4
|
+
require 'gitchefsync/git_util'
|
5
|
+
require 'gitchefsync/errors'
|
6
|
+
require 'gitchefsync/io_util'
|
7
|
+
require 'gitchefsync/config'
|
8
|
+
|
9
|
+
module Gitchefsync
|
10
|
+
|
11
|
+
class KnifeUtil
|
12
|
+
|
13
|
+
def initialize(knife, wd)
|
14
|
+
@knife = knife
|
15
|
+
@wd = wd
|
16
|
+
end
|
17
|
+
|
18
|
+
#needs knife on the command path
|
19
|
+
#parses the knife command "cookbook list -a"
|
20
|
+
#returns a list of cookbooks
|
21
|
+
def listCookbooks
|
22
|
+
list = Array.new
|
23
|
+
str = FS.cmd "cd #{@wd} && #{@knife} cookbook list -a"
|
24
|
+
arr_str = str.split(/\n/)
|
25
|
+
arr_str.each do |line|
|
26
|
+
cb_name, *cb_versions = line.split(' ')
|
27
|
+
cb_versions.each do |cb_version|
|
28
|
+
list << Cookbook.new(cb_name, cb_version)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
list
|
32
|
+
end
|
33
|
+
|
34
|
+
#get a list of existing environment names on chef server
|
35
|
+
def listEnv
|
36
|
+
list = Array.new
|
37
|
+
str = FS.cmd "cd #{@wd} && #{@knife} environment list"
|
38
|
+
environments = str.split(/\n/)
|
39
|
+
environments.each do |env|
|
40
|
+
list << env.strip
|
41
|
+
end
|
42
|
+
list
|
43
|
+
end
|
44
|
+
|
45
|
+
#get a list of existing data bags items (in [bag, item] pairs) on chef server
|
46
|
+
def listDB
|
47
|
+
list = Array.new
|
48
|
+
str = FS.cmd "cd #{@wd} && #{@knife} data bag list"
|
49
|
+
data_bags = str.split(/\n/)
|
50
|
+
data_bags.each do |bag|
|
51
|
+
data_bag_items = showDBItem bag.strip
|
52
|
+
data_bag_items.each do |item|
|
53
|
+
list << [bag.strip, item.strip]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
list
|
57
|
+
end
|
58
|
+
|
59
|
+
#get a list of existing data bag items (from specified bag) on chef server
|
60
|
+
def showDBItem bag
|
61
|
+
list = Array.new
|
62
|
+
str = FS.cmd "cd #{@wd} && #{@knife} data bag show #{bag}"
|
63
|
+
data_bag_items = str.split(/\n/)
|
64
|
+
data_bag_items.each do |item|
|
65
|
+
list << item.strip
|
66
|
+
end
|
67
|
+
list
|
68
|
+
end
|
69
|
+
|
70
|
+
#get a list of existing role names on chef server
|
71
|
+
def listRole
|
72
|
+
list = Array.new
|
73
|
+
str = FS.cmd "cd #{@wd} && #{@knife} role list"
|
74
|
+
roles = str.split(/\n/)
|
75
|
+
roles.each do |role|
|
76
|
+
list << role.strip
|
77
|
+
end
|
78
|
+
list
|
79
|
+
end
|
80
|
+
|
81
|
+
#checks if the cookbook name and version exist in the
|
82
|
+
#array of cookbooks
|
83
|
+
#@param name - name of cookbook
|
84
|
+
#@param version - version of cookbook
|
85
|
+
#@param list - the list of cookbooks - from listCookbooks
|
86
|
+
def inList( name, version, list)
|
87
|
+
found = false
|
88
|
+
list.each do |item|
|
89
|
+
found = true if ( (name == item.name) and (version == item.version))
|
90
|
+
end
|
91
|
+
found
|
92
|
+
end
|
93
|
+
|
94
|
+
#Checks to see if cookbook given is in list
|
95
|
+
#uses inList method to determine it
|
96
|
+
def isCBinList(cookbook, list)
|
97
|
+
return inList( cookbook.name, cookbook.version, list)
|
98
|
+
end
|
99
|
+
|
100
|
+
#returns a list of are in list1 that are not in list2
|
101
|
+
def subtract(list1,list2)
|
102
|
+
list = Array.new
|
103
|
+
list1.each do |cookbook|
|
104
|
+
if !isCBinList(cookbook,list2)
|
105
|
+
list << cookbook
|
106
|
+
end
|
107
|
+
end
|
108
|
+
list
|
109
|
+
end
|
110
|
+
|
111
|
+
#delete a cookbook from the server
|
112
|
+
def delCookbook(cb)
|
113
|
+
begin
|
114
|
+
FS.cmd("cd #{@wd} && knife cookbook delete #{cb.name} #{cb.version} -y" )
|
115
|
+
rescue CmdError => e
|
116
|
+
Gitchefsync.logger.error "event_id=cb_del:#{e.message}:e=#{e.backtrace}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
#Parse metadata.rb from a given directory path
|
121
|
+
def parseMetaData(path)
|
122
|
+
#Gitchefsync.logger.debug "Parsing metadata: #{path}"
|
123
|
+
if !File.exists?(File.join(path, "metadata.rb"))
|
124
|
+
raise NoMetaDataError
|
125
|
+
end
|
126
|
+
contents = ""
|
127
|
+
begin
|
128
|
+
file = File.new(File.join(path, "metadata.rb"), "r")
|
129
|
+
|
130
|
+
contents = file.read
|
131
|
+
version = attr_val(contents,"version")
|
132
|
+
name = attr_val(contents,"name")
|
133
|
+
|
134
|
+
if name.nil?
|
135
|
+
Gitchefsync.logger.warn "event_id=parse_meta_err_name:msg=cannot be resolved, deferring to directory name #{path}"
|
136
|
+
name = File.basename path
|
137
|
+
end
|
138
|
+
#parse maintainer information
|
139
|
+
maintainer = attr_val(contents,"maintainer")
|
140
|
+
email = attr_val(contents,"maintainer_email")
|
141
|
+
|
142
|
+
#puts "matched:#{name}:#{version}"
|
143
|
+
return Cookbook.new(name, version,maintainer,email)
|
144
|
+
rescue Exception => e
|
145
|
+
puts e.backtrace
|
146
|
+
Gitchefsync.logger.error "#{e.backtrace}"
|
147
|
+
raise KnifeError, "Unable to parse data: file=#{path}/metadata.rb #{contents}"
|
148
|
+
ensure
|
149
|
+
file.close unless file.nil?
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def attr_val(contents, name)
|
154
|
+
m1 = contents.match(/#{name}\s+['|"](.*)['|"]/)
|
155
|
+
val = nil
|
156
|
+
if m1 != nil && m1.length == 2
|
157
|
+
val = m1[1]
|
158
|
+
else
|
159
|
+
Gitchefsync.logger.warn "event_id=parse_warn:name=#{name}"
|
160
|
+
end
|
161
|
+
val
|
162
|
+
end
|
163
|
+
end #end class
|
164
|
+
|
165
|
+
#A cookbook description
|
166
|
+
#may include a hash or other description
|
167
|
+
class Cookbook
|
168
|
+
|
169
|
+
def initialize(name,version,maintainer = "", maintainer_email = "")
|
170
|
+
@name = name
|
171
|
+
@version = version
|
172
|
+
@maintainer = maintainer
|
173
|
+
@maintainer_email = maintainer_email
|
174
|
+
end
|
175
|
+
|
176
|
+
def name
|
177
|
+
@name
|
178
|
+
end
|
179
|
+
|
180
|
+
def version
|
181
|
+
@version
|
182
|
+
end
|
183
|
+
|
184
|
+
def maintainer
|
185
|
+
@maintainer
|
186
|
+
end
|
187
|
+
|
188
|
+
def setMaintainer(maintainer)
|
189
|
+
@maintainer = maintainer
|
190
|
+
end
|
191
|
+
|
192
|
+
def maintainer_email
|
193
|
+
@maintainer_email
|
194
|
+
end
|
195
|
+
|
196
|
+
def setMaintainer_email(maintainer_email)
|
197
|
+
@maintainer_email = maintainer_email
|
198
|
+
end
|
199
|
+
|
200
|
+
def to_s
|
201
|
+
return @name + "_" + @version
|
202
|
+
end
|
203
|
+
|
204
|
+
#name convention of how berks packages
|
205
|
+
def berksTar
|
206
|
+
return @name + "-" + @version + ".tar.gz"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Gitchefsync
|
2
|
+
module Log
|
3
|
+
#Wrapped sys log Logger
|
4
|
+
#Overload all the logger methods - although substitution is not covered
|
5
|
+
class SysLogger
|
6
|
+
|
7
|
+
#TODO: may define syslog open at this point
|
8
|
+
def initialize(name)
|
9
|
+
begin
|
10
|
+
Syslog.open(name, Syslog::LOG_PID, Syslog::LOG_LOCAL1)
|
11
|
+
rescue Exception => e
|
12
|
+
puts "Syslog error: #{e.message}"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def debug(*args)
|
18
|
+
log(Syslog::LOG_DEBUG,args[0])
|
19
|
+
end
|
20
|
+
|
21
|
+
def info(*args)
|
22
|
+
log(Syslog::LOG_INFO,args[0])
|
23
|
+
end
|
24
|
+
|
25
|
+
def warn(*args)
|
26
|
+
log(Syslog::LOG_WARNING,args[0])
|
27
|
+
end
|
28
|
+
|
29
|
+
def error(*args)
|
30
|
+
log(Syslog::LOG_ERR,args[0])
|
31
|
+
end
|
32
|
+
|
33
|
+
def fatal(*args)
|
34
|
+
log(Syslog::LOG_EMERG,args[0])
|
35
|
+
end
|
36
|
+
|
37
|
+
def log ( level, msg)
|
38
|
+
begin
|
39
|
+
Syslog.log(level, msg)
|
40
|
+
ensure
|
41
|
+
#Syslog.close
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'gitchefsync/audit'
|
2
|
+
require 'gitchefsync/io_util'
|
3
|
+
require 'net/smtp'
|
4
|
+
|
5
|
+
module Gitchefsync
|
6
|
+
|
7
|
+
class Notification
|
8
|
+
|
9
|
+
def initialize(smtp="mail.rim.net", from="mandolin@blackberry.com",to='mandolin@blackberry.com', msg="")
|
10
|
+
@to = to
|
11
|
+
@from = from
|
12
|
+
@smtp = smtp = Net::SMTP.start(smtp, 25)
|
13
|
+
@hostname = FS.cmd "hostname"
|
14
|
+
end
|
15
|
+
|
16
|
+
def notifyFromAudit(audit_dir, audit_type)
|
17
|
+
audit = Audit.new(audit_dir,audit_type)
|
18
|
+
audit_list = audit.latestAuditItems
|
19
|
+
|
20
|
+
audit_list.each do |audit_item|
|
21
|
+
if audit_item.ex != nil
|
22
|
+
h = audit_item.to_hash
|
23
|
+
msg = "From: gichefsync <mandolin@blackberry.com>\nTo: #{h[:maintainer]} #{h[:maintainer_email]}\nSubject: gitchefsync failure\n"
|
24
|
+
msg << "Alert from Hostname: #{@hostname}\n\n"
|
25
|
+
msg << "Attention!\n\n"
|
26
|
+
msg << "gitchefsync has identified you as the maintainer of this artifact\n"
|
27
|
+
msg << "====================================\n"
|
28
|
+
msg << "#{h[:name]}:#{h[:version]}\n"
|
29
|
+
msg << "====================================\n"
|
30
|
+
msg << "#{h[:exception]}"
|
31
|
+
|
32
|
+
sendTo(h[:maintainer_email],msg)
|
33
|
+
Gitchefsync.logger.info("event_id=email_sent=#{h[:maintainer_email]} ")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
Gitchefsync.logger.info("event_id=notification_complete:audit_type=#{audit_type}")
|
37
|
+
end
|
38
|
+
|
39
|
+
#Aggregates a single email to the "to" email parameter
|
40
|
+
def singleNotifyFromAudit(audit_dir,audit_type,to)
|
41
|
+
audit = Audit.new(audit_dir,audit_type)
|
42
|
+
audit_list = audit.latestAuditItems
|
43
|
+
msg = "From: gichefsync <mandolin@blackberry.com>\nTo: #{to}\nSubject: gitchefsync failure: summary\n\n"
|
44
|
+
msg << "Alert from Hostname: #{@hostname}\n\n"
|
45
|
+
audit_list.each do |audit_item|
|
46
|
+
h = audit_item.to_hash
|
47
|
+
|
48
|
+
if h[:exception] != nil
|
49
|
+
ver = ""
|
50
|
+
if !h[:version].empty? then ver = ":" + h[:version] end
|
51
|
+
|
52
|
+
msg << "item: #{h[:name]}#{ver} was NOT processed with status #{h[:action]} "
|
53
|
+
msg << "\nERROR #{h[:exception]}"
|
54
|
+
else
|
55
|
+
msg << "item: #{h[:name]} was NOT processed with status #{h[:action]} "
|
56
|
+
end
|
57
|
+
msg << "\n\n"
|
58
|
+
end
|
59
|
+
sendTo(to,msg)
|
60
|
+
end
|
61
|
+
|
62
|
+
def send(body)
|
63
|
+
@smtp.send_message body, @from, @to
|
64
|
+
end
|
65
|
+
|
66
|
+
def sendTo(send_to, body)
|
67
|
+
@smtp.send_message body, @from, send_to
|
68
|
+
end
|
69
|
+
|
70
|
+
def close
|
71
|
+
@smtp.finish
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'gitlab'
|
2
|
+
require 'gitchefsync/errors'
|
3
|
+
module Gitchefsync
|
4
|
+
|
5
|
+
module Parser
|
6
|
+
|
7
|
+
def self.parseOpts (args)
|
8
|
+
options = {}
|
9
|
+
begin
|
10
|
+
|
11
|
+
opt_parser = OptionParser.new do |opts|
|
12
|
+
opts.banner = "Usage: sync_all.rb --private_token=xyz OR LDAP credentials"
|
13
|
+
options[:private_token] = ''
|
14
|
+
opts.on('-t', '--private_token token','gitlab private token') do |token|
|
15
|
+
options[:private_token] = token
|
16
|
+
end
|
17
|
+
options[:config_file] = './sync-config.json'
|
18
|
+
opts.on('-c', '--config file','path to config file') do |token|
|
19
|
+
options[:config_file] = token
|
20
|
+
end
|
21
|
+
options[:login] = ''
|
22
|
+
opts.on('-l','--login login','Required when token not set') do |login|
|
23
|
+
options[:login] = login
|
24
|
+
end
|
25
|
+
options[:password] = ''
|
26
|
+
opts.on('-p','--password password','Required when token not set') do |pass|
|
27
|
+
options[:password] = pass
|
28
|
+
end
|
29
|
+
opts.on('-s','--syslog',"Enable syslog") do |syslog|
|
30
|
+
options[:syslog] = true
|
31
|
+
end
|
32
|
+
opts.on('-u', '--giturl', "Gitlab url") do |giturl|
|
33
|
+
Gitlab.endpoint = giturl
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
opt_parser.parse! (args)
|
38
|
+
|
39
|
+
json = File.read(options[:config_file])
|
40
|
+
|
41
|
+
j_config = JSON.parse(json)
|
42
|
+
options[:config] = j_config
|
43
|
+
options[:git_local] = j_config['working_directory']
|
44
|
+
options[:knife_config] = j_config['knife_file']
|
45
|
+
options[:groups] = j_config['git_groups']
|
46
|
+
options[:stage_cookbook_dir] = j_config['tmp_dir']
|
47
|
+
|
48
|
+
#set gitlab token and ensure git url for backward compatibility
|
49
|
+
if Gitlab.endpoint == nil
|
50
|
+
Gitlab.endpoint = 'https://gitlab.rim.net/api/v3'
|
51
|
+
end
|
52
|
+
if options[:private_token].empty? && !options[:login].empty? && !options[:password].empty?
|
53
|
+
puts "using credentials"
|
54
|
+
options[:private_token] = Gitlab.session(options[:login],options[:password]).to_hash['private_token']
|
55
|
+
end
|
56
|
+
|
57
|
+
rescue Exception => e
|
58
|
+
puts e.backtrace
|
59
|
+
raise(ConfigError,e.message,e.backtrace)
|
60
|
+
end
|
61
|
+
options
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
module Gitchefsync
|
4
|
+
class ScheduleSync
|
5
|
+
|
6
|
+
def initialize()
|
7
|
+
options = Gitchefsync.options
|
8
|
+
config = Gitchefsync.configuration
|
9
|
+
|
10
|
+
@lock_filename = config['lock_filename'] || 'sync.lock'
|
11
|
+
@lock_timeout = config['lock_timeout'] || 10
|
12
|
+
@lock_timeout = @lock_timeout.to_i
|
13
|
+
|
14
|
+
@master_sync_timeout = config['master_sync_timeout'] || 600
|
15
|
+
@master_sync_timeout = @master_sync_timeout.to_i
|
16
|
+
|
17
|
+
@sous_rsync_user = config['sous_rsync_user'] || 'chefsync'
|
18
|
+
@sous_rsync_host = config['sous_rsync_host'] || ''
|
19
|
+
@sous_rsync_src = config['sous_rsync_src'] || config['stage_dir'] || '/opt/gitchefsync/staging/'
|
20
|
+
@sous_rsync_dest = config['sous_rsync_dest'] ||
|
21
|
+
File.join(File::SEPARATOR, config['stage_dir'].split(File::SEPARATOR)[1..-2]) ||
|
22
|
+
'/opt/gitchefsync/'
|
23
|
+
@sous_rsync_options = config['sous_rsync_options'] || '-ar --delete'
|
24
|
+
@sous_rsync_excludes = config['sous_rsync_excludes'] || '.chef .snapshot'
|
25
|
+
|
26
|
+
@sous_sync_timeout = config['sous_sync_timeout'] || 600
|
27
|
+
@sous_sync_timeout = @sous_sync_timeout.to_i
|
28
|
+
end
|
29
|
+
|
30
|
+
def obtainExclusiveLock
|
31
|
+
Gitchefsync.logger.info "event_id=attempt_to_lock_file:lock_filename=#{@lock_filename}"
|
32
|
+
lock_file = File.open(@lock_filename, File::RDWR|File::CREAT, 0644)
|
33
|
+
|
34
|
+
begin
|
35
|
+
Timeout::timeout(@lock_timeout) { lock_file.flock(File::LOCK_EX) }
|
36
|
+
rescue
|
37
|
+
Gitchefsync.logger.fatal "event_id=unable_to_lock_file:lock_filename=#{@lock_filename}"
|
38
|
+
exit 1
|
39
|
+
end
|
40
|
+
|
41
|
+
lock_file
|
42
|
+
end
|
43
|
+
|
44
|
+
def master
|
45
|
+
lock_file = obtainExclusiveLock
|
46
|
+
|
47
|
+
begin
|
48
|
+
Timeout::timeout(@master_sync_timeout) do
|
49
|
+
Gitchefsync.logger.info "event_id=master_sync_starting"
|
50
|
+
|
51
|
+
#Setup and check Gitlab API endpoint
|
52
|
+
Gitlab.endpoint = 'http://gitlab.rim.net/api/v3'
|
53
|
+
Gitchefsync.checkGit
|
54
|
+
|
55
|
+
Gitchefsync.syncEnv
|
56
|
+
Gitchefsync.syncCookbooks
|
57
|
+
Gitchefsync.reconcile
|
58
|
+
cleanTmp()
|
59
|
+
Gitchefsync.logger.info "event_id=master_sync_completed"
|
60
|
+
|
61
|
+
# MAND-615 - This file will signal its ok for this directory to be sous sync target
|
62
|
+
File.write(File.join(@sous_rsync_src, "master_sync_completed"), "")
|
63
|
+
end
|
64
|
+
rescue Timeout::Error
|
65
|
+
Gitchefsync.logger.fatal "event_id=master_sync_timed_out:master_sync_timeout=#{@master_sync_timeout}"
|
66
|
+
exit 1
|
67
|
+
rescue => e
|
68
|
+
Gitchefsync.logger.error "event_id=caught_exception:msg=#{e.message}"
|
69
|
+
end
|
70
|
+
lock_file.close
|
71
|
+
end
|
72
|
+
|
73
|
+
def sous
|
74
|
+
lock_file = obtainExclusiveLock
|
75
|
+
|
76
|
+
begin
|
77
|
+
Timeout::timeout(@sous_sync_timeout) do
|
78
|
+
Gitchefsync.logger.info "event_id=sous_sync_starting"
|
79
|
+
|
80
|
+
exclude = ""
|
81
|
+
@sous_rsync_excludes.split(" ").each do |pattern|
|
82
|
+
exclude = "#{exclude} --exclude #{pattern}"
|
83
|
+
end
|
84
|
+
|
85
|
+
if @sous_rsync_host.empty?
|
86
|
+
Gitchefsync.logger.fatal "event_id=sous_rsync_host_not_configured"
|
87
|
+
exit 1
|
88
|
+
end
|
89
|
+
|
90
|
+
master_sync_completed = File.join(@sous_rsync_src, "master_sync_completed")
|
91
|
+
master_sync_completed_cmd = "ssh #{@sous_rsync_user}@#{@sous_rsync_host} ls #{master_sync_completed} 2>/dev/null"
|
92
|
+
Gitchefsync.logger.info "event_id=check_master_sync_completed:cmd=#{master_sync_completed_cmd}"
|
93
|
+
master_sync_completed_stdout = FS.cmd "#{master_sync_completed_cmd}"
|
94
|
+
|
95
|
+
# MAND-615 - Do not perform an rsync on #{master_sync_completed} target if empty.
|
96
|
+
# Avoid doing rsync command and staged cookbook/env upload in situation where master
|
97
|
+
# chef server was re-instantiated and master sync has yet to run once.
|
98
|
+
if master_sync_completed_stdout.empty?
|
99
|
+
Gitchefsync.logger.fatal "event_id=missing_master_sync_completed_file:master_sync_completed=#{master_sync_completed}"
|
100
|
+
exit 1
|
101
|
+
end
|
102
|
+
|
103
|
+
rsync_cmd = "rsync #{@sous_rsync_options} #{exclude} #{@sous_rsync_user}@#{@sous_rsync_host}:#{@sous_rsync_src} #{@sous_rsync_dest} 2>/dev/null"
|
104
|
+
Gitchefsync.logger.info "event_id=execute_rsync:cmd=#{rsync_cmd}"
|
105
|
+
FS.cmd "#{rsync_cmd}"
|
106
|
+
|
107
|
+
Gitchefsync.stagedUpload
|
108
|
+
Gitchefsync.syncEnv
|
109
|
+
Gitchefsync.reconcile
|
110
|
+
cleanTmp()
|
111
|
+
Gitchefsync.logger.info "event_id=sous_sync_completed"
|
112
|
+
end
|
113
|
+
rescue Timeout::Error
|
114
|
+
Gitchefsync.logger.fatal "event_id=sous_sync_timed_out:sous_sync_timeout=#{@sous_sync_timeout}"
|
115
|
+
exit 1
|
116
|
+
rescue => e
|
117
|
+
Gitchefsync.logger.error "event_id=caught_exception:msg=#{e.message}"
|
118
|
+
end
|
119
|
+
lock_file.close
|
120
|
+
end
|
121
|
+
|
122
|
+
#Due to ridley bug (4.0.0+ possibly earlier) -clean the tmp directories
|
123
|
+
#takes current "Date" and cleans up
|
124
|
+
def cleanTmp
|
125
|
+
ts_str = "/tmp/d" + Date.today.strftime("%Y%m%d") + "-*"
|
126
|
+
Gitchefsync.logger.info "clean up of #{ts_str}"
|
127
|
+
FS.cmdNoError "sudo rm -fr #{ts_str}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.runMasterSync
|
132
|
+
scheduleSync = ScheduleSync.new()
|
133
|
+
scheduleSync.master
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.runSousSync
|
137
|
+
#force loocal sync
|
138
|
+
options[:config]['sync_local'] = "true"
|
139
|
+
|
140
|
+
#Make sure sous sync only runs on the primary node
|
141
|
+
drbd_connection_state = FS.cmd("sudo drbdadm cstate chef_disk",
|
142
|
+
{ "TERM" => "xterm", "PATH" => "/usr/sbin:/usr/bin:/bin:/sbin" })
|
143
|
+
drbd_role = FS.cmd("sudo drbdadm role chef_disk",
|
144
|
+
{ "TERM" => "xterm", "PATH" => "/usr/sbin:/usr/bin:/bin:/sbin" })
|
145
|
+
|
146
|
+
drbd_connection_state.delete!("\n")
|
147
|
+
drbd_role.delete!("\n")
|
148
|
+
|
149
|
+
connected = drbd_connection_state.match(/Connected/)
|
150
|
+
role = drbd_role.match(/^Primary/)
|
151
|
+
|
152
|
+
if connected and role
|
153
|
+
Gitchefsync.logger.info "event_id=proceed_to_sous_sync:drbd_connection_state=#{connected}:drbd_role=#{role}"
|
154
|
+
scheduleSync = ScheduleSync.new()
|
155
|
+
scheduleSync.sous
|
156
|
+
elsif
|
157
|
+
Gitchefsync.logger.fatal "event_id=abort_sous_sync:drbd_connection_state=#{connected}:drbd_role=#{role}"
|
158
|
+
exit 1
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|