summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server/Reports/reports/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Bcfg2/Server/Reports/reports/models.py')
-rw-r--r--src/lib/Bcfg2/Server/Reports/reports/models.py139
1 files changed, 90 insertions, 49 deletions
diff --git a/src/lib/Bcfg2/Server/Reports/reports/models.py b/src/lib/Bcfg2/Server/Reports/reports/models.py
index 35f2a4393..73adaaaaf 100644
--- a/src/lib/Bcfg2/Server/Reports/reports/models.py
+++ b/src/lib/Bcfg2/Server/Reports/reports/models.py
@@ -23,16 +23,13 @@ KIND_CHOICES = (
('Path', 'symlink'),
('Service', 'Service'),
)
-PING_CHOICES = (
- #These are possible ping states
- ('Up (Y)', 'Y'),
- ('Down (N)', 'N')
-)
+TYPE_GOOD = 0
TYPE_BAD = 1
TYPE_MODIFIED = 2
TYPE_EXTRA = 3
TYPE_CHOICES = (
+ (TYPE_GOOD, 'Good'),
(TYPE_BAD, 'Bad'),
(TYPE_MODIFIED, 'Modified'),
(TYPE_EXTRA, 'Extra'),
@@ -87,30 +84,9 @@ class Client(models.Model):
pass
-class Ping(models.Model):
- """Represents a ping of a client (sparsely)."""
- client = models.ForeignKey(Client, related_name="pings")
- starttime = models.DateTimeField()
- endtime = models.DateTimeField()
- status = models.CharField(max_length=4, choices=PING_CHOICES) # up/down
-
- class Meta:
- get_latest_by = 'endtime'
-
-
class InteractiveManager(models.Manager):
"""Manages interactions objects."""
- def recent_interactions_dict(self, maxdate=None, active_only=True):
- """
- Return the most recent interactions for clients as of a date.
-
- This method uses aggregated queries to return a ValuesQueryDict object.
- Faster then raw sql since this is executed as a single query.
- """
-
- return list(self.values('client').annotate(max_timestamp=Max('timestamp')).values())
-
def interaction_per_client(self, maxdate=None, active_only=True):
"""
Returns the most recent interactions for clients as of a date
@@ -154,15 +130,15 @@ class InteractiveManager(models.Manager):
cursor.execute(sql)
return [item[0] for item in cursor.fetchall()]
except:
- '''FIXME - really need some error hadling'''
+ '''FIXME - really need some error handling'''
pass
return []
class Interaction(models.Model):
"""Models each reconfiguration operation interaction between client and server."""
- client = models.ForeignKey(Client, related_name="interactions",)
- timestamp = models.DateTimeField() # Timestamp for this record
+ client = models.ForeignKey(Client, related_name="interactions")
+ timestamp = models.DateTimeField(db_index=True) # Timestamp for this record
state = models.CharField(max_length=32) # good/bad/modified/etc
repo_rev_code = models.CharField(max_length=64) # repo revision at time of interaction
goodcount = models.IntegerField() # of good config-items
@@ -270,27 +246,47 @@ class Interaction(models.Model):
class Reason(models.Model):
"""reason why modified or bad entry did not verify, or changed."""
- owner = models.TextField(max_length=128, blank=True)
- current_owner = models.TextField(max_length=128, blank=True)
- group = models.TextField(max_length=128, blank=True)
- current_group = models.TextField(max_length=128, blank=True)
- perms = models.TextField(max_length=4, blank=True) # txt fixes typing issue
- current_perms = models.TextField(max_length=4, blank=True)
- status = models.TextField(max_length=3, blank=True) # on/off/(None)
- current_status = models.TextField(max_length=1, blank=True) # on/off/(None)
- to = models.TextField(max_length=256, blank=True)
- current_to = models.TextField(max_length=256, blank=True)
- version = models.TextField(max_length=128, blank=True)
- current_version = models.TextField(max_length=128, blank=True)
+ owner = models.CharField(max_length=255, blank=True)
+ current_owner = models.CharField(max_length=255, blank=True)
+ group = models.CharField(max_length=255, blank=True)
+ current_group = models.CharField(max_length=255, blank=True)
+ perms = models.CharField(max_length=4, blank=True)
+ current_perms = models.CharField(max_length=4, blank=True)
+ status = models.CharField(max_length=128, blank=True)
+ current_status = models.CharField(max_length=128, blank=True)
+ to = models.CharField(max_length=1024, blank=True)
+ current_to = models.CharField(max_length=1024, blank=True)
+ version = models.CharField(max_length=1024, blank=True)
+ current_version = models.CharField(max_length=1024, blank=True)
current_exists = models.BooleanField() # False means its missing. Default True
- current_diff = models.TextField(max_length=1280, blank=True)
+ current_diff = models.TextField(max_length=1024*1024, blank=True)
is_binary = models.BooleanField(default=False)
is_sensitive = models.BooleanField(default=False)
- unpruned = models.TextField(max_length=1280, blank=True)
+ unpruned = models.TextField(max_length=4096, blank=True, default='')
def _str_(self):
return "Reason"
+ def short_list(self):
+ rv = []
+ if self.current_owner or self.current_group or self.current_perms:
+ rv.append("File permissions")
+ if self.current_status:
+ rv.append("Incorrect status")
+ if self.current_to:
+ rv.append("Incorrect target")
+ if self.current_version or self.version == 'auto':
+ rv.append("Wrong version")
+ if not self.current_exists:
+ rv.append("Missing")
+ if self.current_diff or self.is_sensitive:
+ rv.append("Incorrect data")
+ if self.unpruned:
+ rv.append("Directory has extra files")
+ if len(rv) == 0:
+ rv.append("Exists")
+ return rv
+
@staticmethod
@transaction.commit_on_success
def prune_orphans():
@@ -316,6 +312,9 @@ class Entries(models.Model):
cursor.execute('delete from reports_entries where not exists (select rei.id from reports_entries_interactions rei where rei.entry_id = reports_entries.id)')
transaction.set_dirty()
+ class Meta:
+ unique_together = ("name", "kind")
+
class Entries_interactions(models.Model):
"""Define the relation between the reason, the interaction and the entry."""
@@ -343,10 +342,52 @@ class Performance(models.Model):
transaction.set_dirty()
-class InternalDatabaseVersion(models.Model):
- """Object that tell us to witch version is the database."""
- version = models.IntegerField()
- updated = models.DateTimeField(auto_now_add=True)
+class Group(models.Model):
+ """
+ Groups extracted from interactions
+
+ name - The group name
+
+ TODO - Most of this is for future use
+ TODO - set a default group
+ """
+
+ name = models.CharField(max_length=255, unique=True)
+ profile = models.BooleanField(default=False)
+ public = models.BooleanField(default=False)
+ category = models.CharField(max_length=1024, blank=True)
+ comment = models.TextField(blank=True)
+
+ groups = models.ManyToManyField("self", symmetrical=False)
+ bundles = models.ManyToManyField("Bundle")
+
+ def __unicode__(self):
+ return self.name
+
+
+class Bundle(models.Model):
+ """
+ Bundles extracted from interactions
+
+ name - The bundle name
+ """
+
+ name = models.CharField(max_length=255, unique=True)
+
+ def __unicode__(self):
+ return self.name
+
+
+class InteractionMetadata(models.Model):
+ """
+ InteractionMetadata
+
+ Hold extra data associated with the client and interaction
+ """
+
+ interaction = models.OneToOneField(Interaction, primary_key=True, related_name='metadata')
+ profile = models.ForeignKey(Group, related_name="+")
+ groups = models.ManyToManyField(Group)
+ bundles = models.ManyToManyField(Bundle)
+
- def __str__(self):
- return "version %d updated the %s" % (self.version, self.updated.isoformat())