2014-07-14 20:53:04 +00:00
|
|
|
module JamRuby
|
|
|
|
|
class MaxMindRelease < ActiveRecord::Base
|
|
|
|
|
|
|
|
|
|
include S3ManagerMixin
|
|
|
|
|
|
|
|
|
|
@@log = Logging.logger[MaxMindRelease]
|
|
|
|
|
|
|
|
|
|
mount_uploader :geo_ip_124_url, MaxMindReleaseUploader
|
|
|
|
|
mount_uploader :geo_ip_134_url, MaxMindReleaseUploader
|
2014-07-20 02:11:16 +00:00
|
|
|
#mount_uploader :geo_ip_139_url, MaxMindReleaseUploader
|
|
|
|
|
#mount_uploader :geo_ip_142_url, MaxMindReleaseUploader
|
|
|
|
|
mount_uploader :iso3166_url, MaxMindReleaseUploader
|
|
|
|
|
mount_uploader :region_codes_url, MaxMindReleaseUploader
|
|
|
|
|
mount_uploader :table_dumps_url, MaxMindReleaseUploader
|
2014-07-14 20:53:04 +00:00
|
|
|
|
|
|
|
|
def store_dir
|
|
|
|
|
"maxmind/#{released_at}"
|
|
|
|
|
end
|
|
|
|
|
|
2014-07-20 02:11:16 +00:00
|
|
|
# if a dump file is found, use it and specify that COPY should be used
|
|
|
|
|
def file_or_dump(file, dump)
|
|
|
|
|
if dump
|
|
|
|
|
{file: dump, use_copy:true}
|
|
|
|
|
else
|
|
|
|
|
{file: file, use_copy:false}
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def import(force_from_source=false)
|
|
|
|
|
|
|
|
|
|
@@log.debug("-----------------------------------")
|
|
|
|
|
@@log.debug("--------- STARTING IMPORT ---------")
|
|
|
|
|
@@log.debug("-----------------------------------")
|
|
|
|
|
|
|
|
|
|
start = Time.now
|
|
|
|
|
|
|
|
|
|
geo_ip_124_files, geo_ip_134_files, iso3166, region_codes, table_dump_files = download_assets(force_from_source)
|
2014-07-14 20:53:04 +00:00
|
|
|
|
2014-07-20 02:11:16 +00:00
|
|
|
import_to_database(geo_ip_124_files, geo_ip_134_files, iso3166, region_codes, table_dump_files)
|
|
|
|
|
|
|
|
|
|
@@log.debug("IMPORT TOOK: #{Time.now - start} SECONDS")
|
|
|
|
|
@@log.debug("-----------------------------------")
|
|
|
|
|
@@log.debug("--------- FINISHED IMPORT ---------")
|
|
|
|
|
@@log.debug("-----------------------------------")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def import_to_database(geo_ip_124_files, geo_ip_134_files, iso3166, region_codes, table_dump_files = {})
|
|
|
|
|
MaxMindRelease.transaction do
|
|
|
|
|
#MaxMindIsp.import_from_max_mind(file_or_dump(geo_ip_142_files['GeoIPISP-142.csv'], table_dump_files['max_mind_isp.txt']))
|
|
|
|
|
#MaxMindGeo.import_from_max_mind(file_or_dump(geo_ip_139_files['GeoIPCity.csv'], table_dump_files['max_mind_geo.txt']))
|
|
|
|
|
GeoIpBlocks.import_from_max_mind(file_or_dump(geo_ip_134_files['GeoIPCity-134-Blocks.csv'], table_dump_files['geoipblocks.txt']))
|
|
|
|
|
GeoIpLocations.import_from_max_mind(file_or_dump(geo_ip_134_files['GeoIPCity-134-Location.csv'], table_dump_files['geoiplocations.txt']))
|
|
|
|
|
JamIsp.import_from_max_mind(file_or_dump(geo_ip_124_files['GeoIPISP.csv'], table_dump_files['geoipisp.txt']))
|
|
|
|
|
Country.import_from_iso3166(file_or_dump(iso3166, table_dump_files['countries.txt']))
|
|
|
|
|
Region.import_from_region_codes(file_or_dump(region_codes, table_dump_files['regions.txt']))
|
|
|
|
|
|
|
|
|
|
# updating all scores to an old data to jump-start scoring
|
|
|
|
|
@@log.debug("setting all scores 'score_dt' to one day older than initial time")
|
|
|
|
|
Score.connection.execute("UPDATE scores SET score_dt = score_dt - interval '1 day'")
|
|
|
|
|
|
|
|
|
|
# update all user, band, and connection info that is dependent on maxmind
|
|
|
|
|
User.after_maxmind_import
|
|
|
|
|
Connection.after_maxmind_import
|
|
|
|
|
Band.after_maxmind_import
|
|
|
|
|
|
2014-07-21 21:42:30 +00:00
|
|
|
# migrate any scores that need migrating, before we move all the new maxmind content over the old content
|
|
|
|
|
ScoreHistory.migrate_scores
|
|
|
|
|
|
2014-07-20 02:11:16 +00:00
|
|
|
@@log.debug("rename temporary tables over existing tables")
|
|
|
|
|
# replace existing tables with new tables
|
|
|
|
|
GeoIpBlocks.after_maxmind_import
|
|
|
|
|
GeoIpLocations.after_maxmind_import
|
|
|
|
|
JamIsp.after_maxmind_import
|
|
|
|
|
Country.after_maxmind_import
|
|
|
|
|
Region.after_maxmind_import
|
|
|
|
|
|
|
|
|
|
self.imported = true
|
|
|
|
|
self.imported_at = Time.now
|
|
|
|
|
self.save!
|
2014-07-14 20:53:04 +00:00
|
|
|
end
|
2014-07-20 02:11:16 +00:00
|
|
|
end
|
2014-07-14 20:53:04 +00:00
|
|
|
|
2014-07-20 02:11:16 +00:00
|
|
|
def download_assets(force_from_source)
|
2014-07-14 20:53:04 +00:00
|
|
|
working_dir = dated_working_dir
|
|
|
|
|
|
2014-07-20 02:11:16 +00:00
|
|
|
#@@log.debug("downloading and unzipping geoip-142")
|
|
|
|
|
#geo_ip_142_files = download_and_unzip(working_dir, :geo_ip_142_url, self[:geo_ip_142_md5])
|
2014-07-14 20:53:04 +00:00
|
|
|
|
2014-07-20 02:11:16 +00:00
|
|
|
#@@log.debug("downloading and unzipping geoip-139")
|
|
|
|
|
#geo_ip_139_files = download_and_unzip(working_dir, :geo_ip_139_url, self[:geo_ip_139_md5])
|
2014-07-14 20:53:04 +00:00
|
|
|
|
|
|
|
|
@@log.debug("downloading and unzipping geoip-134")
|
|
|
|
|
geo_ip_134_files = download_and_unzip(working_dir, :geo_ip_134_url, self[:geo_ip_134_md5])
|
|
|
|
|
|
|
|
|
|
@@log.debug("downloading and unzipping geoip-124")
|
|
|
|
|
geo_ip_124_files = download_and_unzip(working_dir, :geo_ip_124_url, self[:geo_ip_124_md5])
|
|
|
|
|
|
2014-07-20 02:11:16 +00:00
|
|
|
@@log.debug("downloading region_codes")
|
|
|
|
|
region_codes = download(working_dir, :region_codes_url, self[:region_codes_md5])
|
2014-07-14 20:53:04 +00:00
|
|
|
|
2014-07-20 02:11:16 +00:00
|
|
|
@@log.debug("downloading iso3166")
|
|
|
|
|
iso3166 = download(working_dir, :iso3166_url, self[:iso3166_md5])
|
2014-07-14 20:53:04 +00:00
|
|
|
|
2014-07-20 02:11:16 +00:00
|
|
|
table_dump_files = {}
|
|
|
|
|
if self[:table_dumps_url] && !force_from_source
|
|
|
|
|
@@log.debug("downloading table dumps")
|
|
|
|
|
table_dump_files = download_and_unzip(working_dir, :table_dumps_url, self[:table_dumps_md5])
|
|
|
|
|
end
|
|
|
|
|
return geo_ip_124_files, geo_ip_134_files, iso3166, region_codes, table_dump_files
|
2014-07-14 20:53:04 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def download_and_unzip(working_dir, field, md5)
|
|
|
|
|
downloaded_filename = download(working_dir, field, md5)
|
|
|
|
|
|
|
|
|
|
unzip(working_dir, downloaded_filename)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def download(working_dir, field, md5)
|
|
|
|
|
|
|
|
|
|
filename = File.basename(self[field])
|
|
|
|
|
downloaded_filename = File.join(working_dir, filename)
|
|
|
|
|
@@log.debug("working on field=#{field}, filename #{downloaded_filename}")
|
|
|
|
|
|
|
|
|
|
if File.exists?(downloaded_filename)
|
2014-07-14 22:22:49 +00:00
|
|
|
if matching_md5(downloaded_filename, md5)
|
2014-07-14 20:53:04 +00:00
|
|
|
@@log.debug("#{downloaded_filename} file has matching md5")
|
|
|
|
|
return downloaded_filename
|
|
|
|
|
else
|
|
|
|
|
@@log.debug("#{downloaded_filename} exists but has wrong md5. deleting.")
|
|
|
|
|
File.delete(downloaded_filename)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2015-05-11 21:52:58 +00:00
|
|
|
url = sign_url(field)
|
|
|
|
|
uri = URI(url)
|
2014-07-14 20:53:04 +00:00
|
|
|
open downloaded_filename, 'wb' do |io|
|
2015-05-11 21:52:58 +00:00
|
|
|
Net::HTTP.start(uri.host, uri.port, use_ssl: url.start_with?('https') ? true : false) do |http|
|
2014-07-14 20:53:04 +00:00
|
|
|
request = Net::HTTP::Get.new uri
|
|
|
|
|
http.request request do |response|
|
|
|
|
|
response_code = response.code.to_i
|
|
|
|
|
unless response_code >= 200 && response_code <= 299
|
|
|
|
|
raise "bad status code: #{response_code}. body: #{response.body}"
|
|
|
|
|
end
|
|
|
|
|
response.read_body do |chunk|
|
|
|
|
|
io.write chunk
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
@@log.debug("downloaded #{downloaded_filename}")
|
|
|
|
|
downloaded_filename
|
|
|
|
|
end
|
|
|
|
|
|
2014-07-14 22:22:49 +00:00
|
|
|
def matching_md5(downloaded_filename, md5)
|
|
|
|
|
computed_md5 = Digest::MD5.new
|
|
|
|
|
File.open(downloaded_filename, 'rb').each {|line| computed_md5.update(line)}
|
|
|
|
|
computed_md5.to_s == md5
|
|
|
|
|
end
|
|
|
|
|
|
2014-07-14 20:53:04 +00:00
|
|
|
def unzip(working_dir, downloaded_filename)
|
|
|
|
|
result = {}
|
|
|
|
|
|
|
|
|
|
# overwrites existing files
|
|
|
|
|
Zip.on_exists_proc = true
|
|
|
|
|
|
|
|
|
|
# get the file without extension, to make the output folder name
|
|
|
|
|
extension = File.extname(downloaded_filename)
|
|
|
|
|
name = File.basename(downloaded_filename, extension)
|
|
|
|
|
|
|
|
|
|
output_dir = File.join(working_dir, name)
|
|
|
|
|
Dir.mkdir(output_dir) unless Dir.exists?(output_dir)
|
|
|
|
|
|
|
|
|
|
Zip::File.open(downloaded_filename) do |zip_file|
|
|
|
|
|
# Handle entries one by one
|
|
|
|
|
zip_file.each do |entry|
|
|
|
|
|
# Extract to file/directory/symlink
|
|
|
|
|
|
|
|
|
|
entry_output_dir = File.join(Dir.pwd, output_dir, File.dirname(entry.name))
|
2014-07-14 22:22:49 +00:00
|
|
|
FileUtils.mkdir_p(entry_output_dir)
|
2014-07-14 20:53:04 +00:00
|
|
|
|
|
|
|
|
output_filename = File.join(output_dir, entry.name)
|
2014-07-14 22:22:49 +00:00
|
|
|
File.delete(output_filename) if File.exists?(output_filename)
|
2014-07-14 20:53:04 +00:00
|
|
|
entry.extract(output_filename)
|
|
|
|
|
result[File.basename(entry.name)] = output_filename
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
result
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def dated_working_dir
|
|
|
|
|
# you need a valid working directory from config
|
|
|
|
|
working_dir = APP_CONFIG.max_mind_working_dir
|
|
|
|
|
unless Dir.exists?(working_dir)
|
|
|
|
|
raise "maxmind release working_dir does not exist=#{working_dir}"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# append date, antd download everything to there
|
|
|
|
|
working_dir = File.join(working_dir, released_at.to_s)
|
|
|
|
|
|
|
|
|
|
unless Dir.exists?(working_dir)
|
|
|
|
|
Dir.mkdir(working_dir)
|
|
|
|
|
end
|
|
|
|
|
working_dir
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def sign_url(expiration_time = 120, field)
|
|
|
|
|
resolve_url(field, 'application/zip', expiration_time)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def resolve_url(url_field, mime_type, expiration_time)
|
|
|
|
|
self[url_field].start_with?('http') ? self[url_field] : s3_manager.sign_url(self[url_field], {:expires => expiration_time, :response_content_type => mime_type, :secure => false})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
end
|