CPU_STRINGS = (
### AMD ###
# APU
+ (r"AMD (Sempron)\(tm\) (\d+) APU with Radeon\(tm\) R\d+", r"AMD \1 \2 APU"),
(r"AMD ([\w\-]+) APU with Radeon\(tm\) HD Graphics", r"AMD \1 APU"),
(r"AMD ([\w\-]+) Radeon R\d+, \d+ Compute Cores \d+C\+\d+G", r"AMD \1 APU"),
# Athlon
if location:
self.set_location(location)
+ self.log_profile_update()
+
+ def log_profile_update(self):
+ # Log that an update was performed for this profile id
+ self.db.execute("INSERT INTO fireinfo_profiles_log(public_id) \
+ VALUES(%s)", self.public_id)
+
def expired(self, when=None):
self.db.execute("UPDATE fireinfo_profiles \
SET time_valid = then_or_now(%s) WHERE id = %s", when, self.id)
if not hasattr(self, "_appliance_id"):
appliances = (
("fountainnetworks-prime", self._appliance_test_fountainnetworks_prime),
+ ("lightningwirelabs-eco-plus", self._appliance_test_lightningwirelabs_eco_plus),
("lightningwirelabs-eco", self._appliance_test_lightningwirelabs_eco),
)
if self.appliance_id == "fountainnetworks-prime":
return "Fountain Networks - IPFire Prime Box"
+ elif self.appliance_id == "lightningwirelabs-eco-plus":
+ return "Lightning Wire Labs - IPFire Eco Plus Appliance"
+
elif self.appliance_id == "lightningwirelabs-eco":
return "Lightning Wire Labs - IPFire Eco Appliance"
if not network_adapters_count == 4:
return False
- # 4GB of memory
- if not self.memory >= 4230823936 * 0.95:
+ return True
+
+ def _appliance_test_lightningwirelabs_eco_plus(self):
+ if not self.system_vendor == "ASUS":
+ return False
+
+ if not self.system_model.startswith("P9A-I/2550"):
+ return False
+
+ # Must have four Intel network adapters
+ network_adapters_count = self.count_device("pci", "8086", "1f41")
+ if not network_adapters_count == 4:
return False
return True
# Remove the arch bit
if release:
r = [e for e in release.split() if e]
- for s in ("(i586)", "(armv5tel)"):
+ for s in ("(x86_64)", "(i586)", "(armv5tel)"):
try:
r.remove(s)
break
return False
- def can_update_profile(self, public_id, private_id, when=None):
- res = self.db.get("SELECT 1 FROM fireinfo_profiles \
- WHERE public_id = %s AND private_id = %s \
- AND time_updated + INTERVAL '60 minutes' <= then_or_now(%s) \
- AND time_valid >= then_or_now(%s) ORDER BY time_updated DESC LIMIT 1",
- public_id, private_id, when, when)
+ def profile_rate_limit_active(self, public_id, when=None):
+ # Remove all outdated entries
+ self.db.execute("DELETE FROM fireinfo_profiles_log \
+ WHERE ts <= then_or_now(%s) - INTERVAL '60 minutes'", when)
- if res:
+ res = self.db.get("SELECT COUNT(*) AS count FROM fireinfo_profiles_log \
+ WHERE public_id = %s", public_id)
+
+ if res and res.count >= 10:
return True
return False
+ def is_private_id_change_permitted(self, public_id, private_id, when=None):
+ # Check if a profile exists with a different private id that is still valid
+ res = self.db.get("SELECT 1 FROM fireinfo_profiles \
+ WHERE public_id = %s AND NOT private_id = %s \
+ AND time_valid >= then_or_now(%s) LIMIT 1", public_id, private_id, when)
+
+ if res:
+ return False
+
+ return True
+
def get_profile(self, public_id, private_id=None, when=None):
res = self.db.get("SELECT * FROM fireinfo_profiles \
WHERE public_id = %s AND \
(CASE WHEN %s IS NULL THEN TRUE ELSE private_id = %s END) AND \
- (CASE WHEN %s IS NULL THEN TRUE ELSE \
- then_or_now(%s) BETWEEN time_created AND time_valid END) \
- ORDER BY time_updated DESC LIMIT 1", public_id,
- private_id, private_id, when, when)
+ then_or_now(%s) BETWEEN time_created AND time_valid \
+ ORDER BY time_updated DESC LIMIT 1",
+ public_id, private_id, private_id, when)
+
+ if res:
+ return Profile(self.backend, res.id, res)
+
+ def get_profile_with_data(self, public_id, when=None):
+ res = self.db.get("WITH profiles AS (SELECT fireinfo_profiles_with_data_at(%s) AS id) \
+ SELECT * FROM profiles JOIN fireinfo_profiles ON profiles.id = fireinfo_profiles.id \
+ WHERE public_id = %s ORDER BY time_updated DESC LIMIT 1", when, public_id)
if res:
return Profile(self.backend, res.id, res)
public_id, private_id, when, when, when, valid)
if res:
- return Profile(self.backend, res.id)
+ p = Profile(self.backend, res.id)
+ p.log_profile_update()
+
+ return p
# Devices
profile = self.fireinfo.get_profile(public_id, private_id=private_id, when=when)
# Check if the update can actually be updated
- if profile and not self.fireinfo.can_update_profile(public_id, private_id, when=when):
- logging.warning("Profile not updated because private ID does not"
- " match or last update is too recent: %s" % public_id)
+ if profile and self.fireinfo.profile_rate_limit_active(public_id, when=when):
+ logging.warning("There were too many updates for this profile in the last hour: %s" % public_id)
+ return
+
+ elif not self.is_private_id_change_permitted(public_id, private_id, when=when):
+ logging.warning("Changing private id is not permitted for profile: %s" % public_id)
return
# Parse the profile