]>
git.ipfire.org Git - people/shoehn/ipfire.org.git/blob - www/webapp/backend/mirrors.py
415a9f1df10e6367facec94340f8fba6de0f5d0d
7 import tornado
.httpclient
9 from databases
import Databases
10 from geoip
import GeoIP
11 from misc
import Singleton
13 class Mirrors(object):
14 __metaclass__
= Singleton
18 return Databases().webapp
21 return [Mirror(m
.id) for m
in self
.db
.query("SELECT id FROM mirrors ORDER BY state")]
24 for mirror
in self
.list():
30 def get_by_hostname(self
, hostname
):
31 mirror
= self
.db
.get("SELECT id FROM mirrors WHERE hostname=%s", hostname
)
33 return Mirror(mirror
.id)
35 def get_with_file(self
, filename
, country
=None):
36 # XXX quick and dirty solution - needs a performance boost
37 mirror_ids
= [m
.mirror
for m
in self
.db
.query("SELECT mirror FROM mirror_files WHERE filename=%s", filename
)]
40 # # Sort out all mirrors that are not preferred to the given country
41 # for mirror in self.get_for_country(country):
42 # if not mirror.id in mirror_ids:
43 # mirror_ids.remove(mirror.id)
46 for mirror_id
in mirror_ids
:
47 mirror
= self
.get(mirror_id
)
48 if not mirror
.state
== "UP":
50 mirrors
.append(mirror
)
52 logging
.debug("%s" % mirrors
)
56 def get_for_country(self
, country
):
57 # XXX need option for random order
58 mirrors
= self
.db
.query("SELECT id FROM mirrors WHERE prefer_for_countries LIKE %s", country
)
60 for mirror
in mirrors
:
61 yield self
.get(mirror
.id)
65 def __init__(self
, id):
71 return "<%s %s>" % (self
.__class
__.__name
__, self
.url
)
73 def __cmp__(self
, other
):
74 return cmp(self
.id, other
.id)
78 return Databases().webapp
81 self
._info
= self
.db
.get("SELECT * FROM mirrors WHERE id=%s", self
.id)
82 self
._info
["url"] = self
.generate_url()
84 def generate_url(self
):
85 url
= "http://%s" % self
.hostname
86 if not self
.path
.startswith("/"):
88 url
+= "%s" % self
.path
89 if not self
.path
.endswith("/"):
93 def __getattr__(self
, key
):
95 return self
._info
[key
]
97 raise AttributeError(key
)
101 return socket
.gethostbyname(self
.hostname
)
104 def country_code(self
):
105 return GeoIP().get_country(self
.address
).lower() or "unknown"
109 filelist
= self
.db
.query("SELECT filename FROM mirror_files WHERE mirror=%s ORDER BY filename", self
.id)
110 return [f
.filename
for f
in filelist
]
114 if self
.type.startswith("pakfire"):
119 def set_state(self
, state
):
120 logging
.info("Setting state of %s to %s" % (self
.hostname
, state
))
122 if self
.state
== state
:
125 self
.db
.execute("UPDATE mirrors SET state=%s WHERE id=%s",
128 # Reload changed settings
132 logging
.info("Running check for mirror %s" % self
.hostname
)
134 self
.check_timestamp()
135 self
.check_filelist()
137 def check_state(self
):
138 logging
.debug("Checking state of mirror %s" % self
.id)
140 if self
.disabled
== "Y":
141 self
.set_state("DOWN")
143 time_diff
= time
.time() - self
.last_update
144 if time_diff
> 3*24*60*60: # XXX get this into Settings
145 self
.set_state("DOWN")
146 elif time_diff
> 6*60*60:
147 self
.set_state("OUTOFSYNC")
151 def check_timestamp(self
):
152 if self
.releases
== "N":
155 http
= tornado
.httpclient
.AsyncHTTPClient()
157 http
.fetch(self
.url
+ ".timestamp",
158 headers
={ "Pragma" : "no-cache" },
159 callback
=self
.__check
_timestamp
_response
)
161 def __check_timestamp_response(self
, response
):
163 logging
.debug("Error getting timestamp from %s" % self
.hostname
)
167 timestamp
= int(response
.body
.strip())
171 self
.db
.execute("UPDATE mirrors SET last_update=%s WHERE id=%s",
174 # Reload changed settings
179 logging
.info("Successfully updated timestamp from %s" % self
.hostname
)
181 def check_filelist(self
):
182 # XXX need to remove data from disabled mirrors
183 if self
.releases
== "N" or self
.disabled
== "Y" or self
.type != "full":
186 http
= tornado
.httpclient
.AsyncHTTPClient()
188 http
.fetch(self
.url
+ ".filelist",
189 headers
={ "Pragma" : "no-cache" },
190 callback
=self
.__check
_filelist
_response
)
192 def __check_filelist_response(self
, response
):
194 logging
.debug("Error getting timestamp from %s" % self
.hostname
)
197 self
.db
.execute("DELETE FROM mirror_files WHERE mirror=%s", self
.id)
199 for file in response
.body
.splitlines():
200 self
.db
.execute("INSERT INTO mirror_files(mirror, filename) VALUES(%s, %s)",
201 self
.id, os
.path
.join(self
.prefix
, file))
203 logging
.info("Successfully updated mirror filelist from %s" % self
.hostname
)
206 def prefer_for_countries(self
):
207 return self
._info
.get("prefer_for_countries", "").split()
211 if __name__
== "__main__":
214 for mirror
in m
.list():
215 print mirror
.hostname
, mirror
.country_code