add API to list dirty models and set dirty models
Change-Id: Iea1e67e0cb24845ea329121fa0270f0b2fc21696
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index cd28553..5eb5bda 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -220,9 +220,11 @@
kind = models.CharField(max_length=20, choices=LINK_KIND, default='internal')
def save(self, *args, **kwds):
- existing = XOSComponentLink.objects.filter(container=self.container, alias=self.alias)
- if len(existing) > 0:
- raise XOSValidationError('XOSComponentLink for %s:%s already defined' % (self.container, self.alias))
+ # If this is a new object, then check to make sure it doesn't already exist
+ if not self.pk:
+ existing = XOSComponentLink.objects.filter(container=self.container, alias=self.alias)
+ if len(existing) > 0:
+ raise XOSValidationError('XOSComponentLink for %s:%s already defined' % (self.container, self.alias))
super(XOSComponentLink, self).save(*args, **kwds)
@@ -235,9 +237,11 @@
read_only = models.BooleanField(default=False, help_text="True if mount read-only")
def save(self, *args, **kwds):
- existing = XOSComponentVolume.objects.filter(container_path=self.container_path, host_path=self.host_path)
- if len(existing) > 0:
- raise XOSValidationError('XOSComponentVolume for %s:%s already defined' % (self.container_path, self.host_path))
+ # If this is a new object, then check to make sure it doesn't already exist
+ if not self.pk:
+ existing = XOSComponentVolume.objects.filter(container_path=self.container_path, host_path=self.host_path)
+ if len(existing) > 0:
+ raise XOSValidationError('XOSComponentVolume for %s:%s already defined' % (self.container_path, self.host_path))
super(XOSComponentVolume, self).save(*args, **kwds)
@@ -247,9 +251,11 @@
container = StrippedCharField(max_length=300, help_text="Volume Name")
def save(self, *args, **kwds):
- existing = XOSComponentVolumeContainer.objects.filter(name=self.name)
- if len(existing) > 0:
- raise XOSValidationError('XOSComponentVolumeContainer for %s:%s already defined' % (self.container_path, self.host_path))
+ # If this is a new object, then check to make sure it doesn't already exist
+ if not self.pk:
+ existing = XOSComponentVolumeContainer.objects.filter(name=self.name)
+ if len(existing) > 0:
+ raise XOSValidationError('XOSComponentVolumeContainer for %s:%s already defined' % (self.container_path, self.host_path))
super(XOSComponentVolumeContainer, self).save(*args, **kwds)
diff --git a/xos/coreapi/protos/utility.proto b/xos/coreapi/protos/utility.proto
index 6d5f18f..d899e41 100644
--- a/xos/coreapi/protos/utility.proto
+++ b/xos/coreapi/protos/utility.proto
@@ -28,6 +28,20 @@
string messages = 2;
};
+message ModelFilter {
+ string class_name = 1;
+};
+
+message ModelListEntry {
+ string class_name = 1;
+ int32 id = 2;
+ string info = 3;
+};
+
+message ModelList {
+ repeated ModelListEntry items = 1;
+};
+
service utility {
rpc Login(LoginRequest) returns (LoginResponse) {
@@ -64,4 +78,17 @@
body: "*"
};
}
+
+ rpc SetDirtyModels(ModelFilter) returns (ModelList) {
+ option (google.api.http) = {
+ post: "/xosapi/v1/utility/dirty_models"
+ body: "*"
+ };
+ }
+
+ rpc ListDirtyModels(ModelFilter) returns (ModelList) {
+ option (google.api.http) = {
+ get: "/xosapi/v1/utility/dirty_models"
+ };
+ }
};
diff --git a/xos/coreapi/xos_utility_api.py b/xos/coreapi/xos_utility_api.py
index 7377c91..937bdaf 100644
--- a/xos/coreapi/xos_utility_api.py
+++ b/xos/coreapi/xos_utility_api.py
@@ -1,4 +1,5 @@
import base64
+import fnmatch
import os
import sys
import time
@@ -8,10 +9,11 @@
from importlib import import_module
from django.conf import settings
-SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
+SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
from django.contrib.auth import authenticate as django_authenticate
import django.apps
+from django.db.models import F,Q
from core.models import *
from xos.exceptions import *
from apihelper import XOSAPIHelperMixin
@@ -22,6 +24,20 @@
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
toscadir = os.path.join(currentdir, "../tosca")
+def is_internal_model(model):
+ """ things to be excluded from the dirty_models endpoints """
+ if 'django' in model.__module__:
+ return True
+ if 'cors' in model.__module__:
+ return True
+ if 'contenttypes' in model.__module__:
+ return True
+ if 'core.models.journal' in model.__module__: # why?
+ return True
+ if 'core.models.project' in model.__module__: # why?
+ return True
+ return False
+
class UtilityService(utility_pb2.utilityServicer, XOSAPIHelperMixin):
def __init__(self, thread_pool):
self.thread_pool = thread_pool
@@ -107,3 +123,50 @@
def NoOp(self, request, context):
return Empty()
+ def ListDirtyModels(self, request, context):
+ dirty_models = utility_pb2.ModelList()
+
+ models = django.apps.apps.get_models()
+ for model in models:
+ if is_internal_model(model):
+ continue
+ fieldNames = [x.name for x in model._meta.fields]
+ if (not "enacted" in fieldNames) or (not "updated" in fieldNames):
+ continue
+ if (request.class_name) and (not fnmatch.fnmatch(model.__name__, request.class_name)):
+ continue
+ objs = model.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+ for obj in objs:
+ item = dirty_models.items.add()
+ item.class_name = model.__name__
+ item.id = obj.id
+
+ return dirty_models
+
+ def SetDirtyModels(self, request, context):
+ user=self.authenticate(context, required=True)
+
+ dirty_models = utility_pb2.ModelList()
+
+ models = django.apps.apps.get_models()
+ for model in models:
+ if is_internal_model(model):
+ continue
+ fieldNames = [x.name for x in model._meta.fields]
+ if (not "enacted" in fieldNames) or (not "updated" in fieldNames):
+ continue
+ if (request.class_name) and (not fnmatch.fnmatch(model.__name__, request.class_name)):
+ continue
+ objs = model.objects.all()
+ for obj in objs:
+ try:
+ obj.caller = user
+ obj.save()
+ except Exception, e:
+ item = dirty_models.items.add()
+ item.class_name = model.__name__
+ item.id = obj.id
+ item.info = str(e)
+
+ return dirty_models
+
diff --git a/xos/xos_client/xosapi/xos_grpc_client.py b/xos/xos_client/xosapi/xos_grpc_client.py
index aaaa97f..d0d1f19 100644
--- a/xos/xos_client/xosapi/xos_grpc_client.py
+++ b/xos/xos_client/xosapi/xos_grpc_client.py
@@ -66,6 +66,7 @@
stub_class = getattr(m_grpc, api+"Stub")
setattr(self, api, stub_class(self.channel))
+ setattr(self, api+"_pb2", m_protos)
else:
print >> sys.stderr, "failed to locate api", api