summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Legler <alex@a3li.li>2016-01-04 02:18:48 +0100
committerAlex Legler <alex@a3li.li>2016-01-04 02:18:48 +0100
commitfd7fa9102a50dedb2f1cbad4993fa2c7427407aa (patch)
tree7ca0f15a86f6a84599f076e01e8a27a8e22ec8d2 /lib/mirror_toolkit.rb
downloadmirror-toolkit-fd7fa9102a50dedb2f1cbad4993fa2c7427407aa.tar.gz
mirror-toolkit-fd7fa9102a50dedb2f1cbad4993fa2c7427407aa.tar.bz2
mirror-toolkit-fd7fa9102a50dedb2f1cbad4993fa2c7427407aa.zip
Add initial set of tools
- rsync-cat: rsync-to-stdout utility - gm-lag: displays the current lag of a mirror
Diffstat (limited to 'lib/mirror_toolkit.rb')
-rw-r--r--lib/mirror_toolkit.rb89
1 files changed, 89 insertions, 0 deletions
diff --git a/lib/mirror_toolkit.rb b/lib/mirror_toolkit.rb
new file mode 100644
index 0000000..cc53090
--- /dev/null
+++ b/lib/mirror_toolkit.rb
@@ -0,0 +1,89 @@
+require 'open3'
+require 'time'
+require 'net/http'
+
+# Mirror toolkit functionality and other shared stuff
+module MirrorToolkit
+ RSYNC_TIMESTAMP_FILE = '/gentoo-portage/metadata/timestamp'
+ DISTFILES_TIMESTAMP_FILE = '/distfiles/timestamp.mirmon'
+
+ TYPE_RSYNC = 1
+ TYPE_DISTFILES = 2
+
+ module_function
+
+ # Calls `rsync_cat` to fetch a file from rsync
+ def rsync_cat(uri)
+ rsync_cat = File.join(File.dirname(__FILE__), '..', 'bin', 'rsync-cat')
+ stdin, stdout, stderr, wait_thr = Open3.popen3(rsync_cat, uri)
+ stdin.close
+
+ if wait_thr.value == 0
+ return stdout.gets
+ else
+ fail "Rsync call unsuccessful: '#{stderr.gets.chomp}'"
+ end
+ end
+
+ # Fetches a URI from any of the Gentoo mirror types
+ def remote_fetch(url)
+ case url.scheme
+ when 'rsync'
+ rsync_cat(url.to_s)
+ when 'http', 'https', 'ftp'
+ Net::HTTP.get(url)
+ else
+ fail 'Unknown URI scheme.'
+ end
+ end
+
+ # Tries to return a Time object for every kind of timestamp used on Gentoo mirrors
+ def parse_timestamp(ts)
+ if ts.numeric?
+ Time.at(ts.to_i).utc
+ else
+ Time.parse(ts).utc
+ end
+ end
+
+ # Returns a URI object where to find the timestamp for the given url and mirror type.
+ def get_timestamp_url(url, type)
+ mirror = URI(url)
+
+ case mirror.scheme
+ when 'rsync'
+ if type == TYPE_RSYNC
+ mirror.path = MirrorToolkit::RSYNC_TIMESTAMP_FILE
+ elsif type == TYPE_DISTFILES
+ mirror.path += MirrorToolkit::DISTFILES_TIMESTAMP_FILE
+ end
+ when 'http', 'https', 'ftp'
+ mirror.path = MirrorToolkit::DISTFILES_TIMESTAMP_FILE
+ end
+
+ mirror
+ end
+
+ # Returns the number of seconds a mirror is lagging behind, or nil if it cannot be determined.
+ def get_lag(url, type)
+ Time.now.utc - parse_timestamp(remote_fetch(get_timestamp_url(url, type)))
+ rescue
+ nil
+ end
+
+ # Renders seconds as a nice human-printable string
+ def humanize_seconds(secs)
+ [[60, :seconds], [60, :minutes], [24, :hours], [1000, :days]].map do |count, name|
+ if secs > 0
+ secs, n = secs.divmod(count)
+ "#{n.to_i} #{name}"
+ end
+ end.compact.reverse.join(' ')
+ end
+end
+
+class String
+ def numeric?
+ true if Float(self) rescue false
+ end
+end