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

Methods

Included Modules

Dsadmin::CoreClient Dsadmin::Contractor Dsadmin::ValueChecker MirrorUtils

Attributes

error_msg  [W] 
error_msg  [R] 
mirror  [R] 
transfer_size  [W] 
transfer_size  [R] 

Public Class methods

Factory: Returns a MirrorUpdater derivative suitable for the given mirror

[Source]

     # 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

[Source]

     # 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

Public Instance methods

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

[Source]

    # 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

Protected Instance methods

OVERRIDE!

Has to set transfer_size and (if applicable) error_msg

[Source]

     # File lib/dsadmin/admind/mirror_updater.rb, line 184
184:       def build_statistics(status, stdout, stderr)
185:         assertNotReachable
186:       end

OVERRIDE!

Returns:The ID of the command to execute, as used in the configfile (e.g. "rsync" or "ftpcopy")

[Source]

     # File lib/dsadmin/admind/mirror_updater.rb, line 128
128:       def command_id
129:         assertNotReachable
130:       end

OVERRIDE!

Returns:Array of cmdline parameters specifying the remote/local path, username, host, port and password

[Source]

     # 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.

[Source]

     # 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

[Source]

     # 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")

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

Private Instance methods

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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.

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Validate]