]> git.ipfire.org Git - people/shoehn/ipfire.org.git/blobdiff - webapp/backend/fireinfo.py
fireinfo: Remove x86_64 from release string
[people/shoehn/ipfire.org.git] / webapp / backend / fireinfo.py
index 91abbf47a42df9cd3a784b7f901ec16298fd153d..1f8768085cdaecc9f8c110ffeb6a2d56fed7010f 100644 (file)
@@ -33,6 +33,7 @@ CPU_VENDORS = {
 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
@@ -497,6 +498,13 @@ class Profile(Object):
                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)
@@ -678,6 +686,7 @@ class Profile(Object):
                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),
                        )
 
@@ -696,6 +705,9 @@ class Profile(Object):
                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"
 
@@ -718,8 +730,18 @@ class Profile(Object):
                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
@@ -1388,7 +1410,7 @@ class ProfileParser(Object):
                # 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
@@ -1460,26 +1482,45 @@ class Fireinfo(Object):
 
                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)
@@ -1504,7 +1545,10 @@ class Fireinfo(Object):
                        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
 
@@ -1663,9 +1707,12 @@ class Fireinfo(Object):
                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