| Class | Dsadmin::Admind::MirrorUpdater |
| In: |
lib/dsadmin/admind/mirror_updater.rb
|
| Parent: | Object |
Base class for mirror updaters.
Designed for one-shot usage:
updater = MirrorUpdater.create(my_mirror) result = updater.update if(result != Mirror::S_SUCCESS) # evaluate updater.error_msg end # do something useful with updater.transfer_size
| error_msg | [W] | |
| error_msg | [R] | |
| mirror | [R] | |
| transfer_size | [W] | |
| transfer_size | [R] |
Factory: Returns a MirrorUpdater derivative suitable for the given mirror
# File lib/dsadmin/admind/mirror_updater.rb, line 101
101: def self.create(mirror)
102: require 'dsadmin/admind/rsync_updater'
103: require 'dsadmin/admind/ftp_updater'
104:
105: case(mirror.kind)
106: when Mirror::T_RSYNC then return RsyncUpdater.new(mirror)
107: when Mirror::T_FTP then return FtpUpdater.new(mirror)
108: else
109: Dsadmin::Logger.instance.bug("Unknown mirror type '#{mirror.kind}'")
110: return nil
111: end
112: end
# File lib/dsadmin/admind/mirror_updater.rb, line 189
189: def initialize(mirror)
190: requireKindOf(Mirror, mirror)
191:
192: @mirror = mirror
193: @transfer_size = 0
194: @error_msg = nil
195:
196: init_loadlimit
197: end
Perform an update of the mirror.
This also takes care of the update statistics logging. The size and last_update timestamp of the mirror have to be updated by the caller. FIX: doing it here would make more sense. Maybe.
| Returns: | Mirror::S_SUCCESS, Mirror::S_DELAYED or Mirror::S_FAILURE |
# File lib/dsadmin/admind/mirror_updater.rb, line 67
67: def update
68: t_start = sys.now
69:
70: cmd = command
71: params = build_parameters
72: cmd.params.push(*params)
73: env = environment || Hash.new
74: if(updatelimit_reached?)
75: log.notice("Update limit reached -- delaying update of #{mirror.name}")
76: return Mirror::S_DELAYED
77: end
78:
79: log.debug("Executing '#{cmd.to_s}' as #{cmd.user}")
80: res = cmd.exec3e(env)
81: # log.debug(" Stdout = #{res['stdout']}")
82: # log.debug(" Stderr = #{res['stderr']}")
83:
84: unless(res['status'].success?)
85: log.notice("Mirror update for '#{mirror.name}' failed")
86: end
87:
88: build_statistics(res['status'], res['stdout'], res['stderr'])
89:
90: if(mirror.flags.include?(Mirror::F_DEBUG))
91: write_debug_data(res['status'], res['stdout'], res['stderr'])
92: end
93:
94: write_timestamp_file
95:
96: return res['status'].success? ? Mirror::S_SUCCESS : Mirror::S_FAILURE
97: end
OVERRIDE!
Has to set transfer_size and (if applicable) error_msg
# File lib/dsadmin/admind/mirror_updater.rb, line 184
184: def build_statistics(status, stdout, stderr)
185: assertNotReachable
186: end
OVERRIDE!
| Returns: | Array of cmdline parameters specifying the remote/local path, username, host, port and password |
# File lib/dsadmin/admind/mirror_updater.rb, line 169
169: def connection_params
170: assertNotReachable
171: end
OVERRIDE!
| Returns: | A Hash of env_var => value to set when executing the cmd. May be nil. |
# File lib/dsadmin/admind/mirror_updater.rb, line 136
136: def environment
137: assertNotReachable
138: end
OVERRIDE!
| Returns: | Array or String of cmdline parameter(s) for the given exclude pattern |
# File lib/dsadmin/admind/mirror_updater.rb, line 177
177: def exclude_param(pattern)
178: assertNotReachable
179: end
OVERRIDE!
| Returns: | Cmdline parameter to use for the given flag (e.g. "—partial") |
# File lib/dsadmin/admind/mirror_updater.rb, line 143
143: def param_name(flag)
144: assertNotReachable
145: end
OVERRIDE!
| Returns: | Order in which the cmdline parameters should be passed |
# File lib/dsadmin/admind/mirror_updater.rb, line 150
150: def param_order
151: [:standard, :flag, :exclude, :connection]
152: end
OVERRIDE!
| Returns: | Array of cmdline parameters that are always present |
# File lib/dsadmin/admind/mirror_updater.rb, line 157
157: def standard_params
158: if(mirror.cmdline_opts)
159: Shellwords::shellwords(mirror.cmdline_opts)
160: else
161: []
162: end
163: end
# File lib/dsadmin/admind/mirror_updater.rb, line 204
204: def build_parameters
205: tmp = Hash.new
206: tmp[:standard] = standard_params
207:
208: tmp[:flag] = []
209: flags = mirror.flags
210:
211: [Mirror::F_DELETE_EXCLUDED,
212: Mirror::F_COMPRESS,
213: Mirror::F_HARD_LINKS,
214: Mirror::F_PARTIAL,
215: Mirror::F_PRESERVE_PERMS,
216: Mirror::F_DEREFERENCE,
217: Mirror::F_DEBUG].each { |i|
218: tmp[:flag] << param_name(i) if(flags.include?(i) && (param_name(i) != nil))
219: }
220:
221: tmp[:exclude] = []
222: if(mirror.exclude_patterns)
223: mirror.exclude_patterns.each { |pat|
224: val = exclude_param(pat)
225: if(val.kind_of?(Array))
226: tmp[:exclude].push(*val)
227: else
228: tmp[:exclude] << val
229: end
230: }
231: end
232:
233: tmp[:connection] = connection_params
234:
235: params = []
236: param_order.each { |key|
237: params.push(*(tmp[key]))
238: }
239: return params
240: end
# File lib/dsadmin/admind/mirror_updater.rb, line 300
300: def command
301: cid = command_id
302: csect = cfg.get("modules/mirror/commands/update/#{cid}", ConfigSection)
303: return Dsadmin::SystemCommand.new(csect)
304: end
# File lib/dsadmin/admind/mirror_updater.rb, line 278
278: def init_loadlimit
279: return if @@loadlimit
280: csect = cfg.get("modules/mirror", ConfigSection)
281:
282: @@loadlimit = Hash.new
283: @@loadlimit['low'] = csect.get("loadlimit/low", Integer)
284: @@loadlimit['medium'] = csect.get("loadlimit/medium", Integer)
285: @@loadlimit['high'] = csect.get("loadlimit/high", Integer)
286: @@loadlimit['abs-bonus'] = csect.get("loadlimit/abs_bonus", Integer)
287: end
Check whether some limit for the update has been reached for the given mirror.
# File lib/dsadmin/admind/mirror_updater.rb, line 293
293: def updatelimit_reached?
294: loadlimit = @@loadlimit[mirror.priority]
295: loadlimit += @@loadlimit['abs-bonus'] if(mirror.update_timespec.absolute?)
296: return (sys.sysload > loadlimit)
297: end
# File lib/dsadmin/admind/mirror_updater.rb, line 243
243: def write_debug_data(status, stdout, stderr)
244: csect = cfg.get("modules/mirror/paths/update_logdir", ConfigSection)
245: path = Dsadmin::SystemPath.new(csect)
246: placeholders = {'MIRRORNAME' => mirror.name,
247: 'TIMESTAMP' => sys.now.strftime("%Y%m%d%H%M%S")}
248:
249: path.makedirs(true, placeholders)
250: path.open(placeholders, 'a') { |fhandle|
251: fhandle.print("Return Code: #{status}\n\n")
252: fhandle.print("stdout:\n")
253: fhandle.write(stdout)
254: fhandle.print("\nstderr:\n")
255: fhandle.write(stderr)
256: }
257: end
# File lib/dsadmin/admind/mirror_updater.rb, line 260
260: def write_timestamp_file
261: return if(mirror.timestamp_file.nil?)
262:
263: path = mirror_path
264: user = mirror_user
265: file = File.join(path, mirror.local_dir, mirror.timestamp_file)
266:
267: assertTrue(path[0..0] == "/")
268:
269: sys.runAs(user) {
270: File.makedirs(File.dirname(file))
271: File.open(file, "w") { |fhandle|
272: fhandle.print(sys.time2string(sys.now))
273: }
274: }
275: end