SEBA-741 Report django version; report version in log

Change-Id: Ic33401414a1ebd075989130f3ea101e6d9e46408
diff --git a/xos/coreapi/grpc_server.py b/xos/coreapi/grpc_server.py
index 5dabb35..ac339f4 100644
--- a/xos/coreapi/grpc_server.py
+++ b/xos/coreapi/grpc_server.py
@@ -34,6 +34,9 @@
 Config.init()
 log = create_logger(Config().get("logging"))
 
+# Must be imported after Config.init()
+from xos_version import get_version_dict
+
 SERVER_KEY = "/opt/cord_profile/core_api_key.pem"
 SERVER_CERT = "/opt/cord_profile/core_api_cert.pem"
 SERVER_CA = "/usr/local/share/ca-certificates/local_certs.crt"
@@ -189,6 +192,8 @@
     def start(self):
         log.info("Starting GRPC Server")
 
+        log.info("XOS Core Build Details", **get_version_dict())
+
         self.service_names = []
 
         self.register(
diff --git a/xos/coreapi/protos/utility.proto b/xos/coreapi/protos/utility.proto
index c351f1f..b0203de 100644
--- a/xos/coreapi/protos/utility.proto
+++ b/xos/coreapi/protos/utility.proto
@@ -41,6 +41,7 @@
     string buildTime = 4;
     string os = 5;
     string arch = 6;
+    string djangoVersion = 7;
 };
 
 message DatabaseInfo {
diff --git a/xos/coreapi/xos_utility_api.py b/xos/coreapi/xos_utility_api.py
index 3ebe405..3e6b90d 100644
--- a/xos/coreapi/xos_utility_api.py
+++ b/xos/coreapi/xos_utility_api.py
@@ -12,7 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import datetime
 import inspect
 from apistats import REQUEST_COUNT, track_request_time
 import grpc
@@ -26,11 +25,11 @@
 from django.contrib.auth import authenticate as django_authenticate
 import fnmatch
 import os
-import sys
 from protos import utility_pb2, utility_pb2_grpc
 from google.protobuf.empty_pb2 import Empty
 from importlib import import_module
 from django.conf import settings
+from xos_version import get_version_dict
 from xosconfig import Config
 from multistructlog import create_logger
 
@@ -281,29 +280,21 @@
         ).inc()
         return response
 
+
     @translate_exceptions("Utilities", "GetVersion")
     @track_request_time("Utilities", "GetVersion")
     def GetVersion(self, request, context):
+        version = get_version_dict()
+
         res = utility_pb2.VersionInfo()
 
-        try:
-            res.version = open("/opt/xos/VERSION").readline().strip()
-        except Exception:
-            log.exception("Exception while determining build version")
-            res.version = "unknown"
-
-        try:
-            res.gitCommit = open("/opt/xos/COMMIT").readline().strip()
-            res.buildTime = datetime.datetime.utcfromtimestamp(
-                os.stat("/opt/xos/COMMIT").st_ctime).strftime("%Y-%m-%dT%H:%M:%SZ")
-        except Exception:
-            log.exception("Exception while determining build information")
-            res.buildDate = "unknown"
-            res.gitCommit = "unknown"
-
-        res.pythonVersion = sys.version.split("\n")[0].strip()
-        res.os = os.uname()[0].lower()
-        res.arch = os.uname()[4].lower()
+        res.version = version["version"]
+        res.gitCommit = version["gitCommit"]
+        res.buildTime = version["buildTime"]
+        res.pythonVersion = version["pythonVersion"]
+        res.os = version["os"]
+        res.arch = version["arch"]
+        res.djangoVersion = version["djangoVersion"]
 
         REQUEST_COUNT.labels(
             "xos-core", "Utilities", "GetVersion", grpc.StatusCode.OK
diff --git a/xos/coreapi/xos_version.py b/xos/coreapi/xos_version.py
new file mode 100644
index 0000000..d2dca16
--- /dev/null
+++ b/xos/coreapi/xos_version.py
@@ -0,0 +1,48 @@
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import datetime
+from django import VERSION as DJANGO_VERSION
+import os
+import sys
+from xosconfig import Config
+from multistructlog import create_logger
+
+log = create_logger(Config().get("logging"))
+
+
+def get_version_dict():
+    """ Return built-time version information """
+    res = {}
+    try:
+        res["version"] = open("/opt/xos/VERSION").readline().strip()
+    except Exception:
+        log.exception("Exception while determining build version")
+        res["version"] = "unknown"
+
+    try:
+        res["gitCommit"] = open("/opt/xos/COMMIT").readline().strip()
+        res["buildTime"] = datetime.datetime.utcfromtimestamp(
+            os.stat("/opt/xos/COMMIT").st_ctime).strftime("%Y-%m-%dT%H:%M:%SZ")
+    except Exception:
+        log.exception("Exception while determining build information")
+        res["buildDate"] = "unknown"
+        res["gitCommit"] = "unknown"
+
+    res["pythonVersion"] = sys.version.split("\n")[0].strip().split(" ")[0]
+    res["os"] = os.uname()[0].lower()
+    res["arch"] = os.uname()[4].lower()
+    res["djangoVersion"] = ".".join([str(x) for x in DJANGO_VERSION])
+
+    return res