Add VERSION file and read version into VOLTHA core.

Add CLI to view VOLTHA core version.

Change-Id: I73eac175d836dec2bb647d0ff74bb33e18580b85
diff --git a/cli/main.py b/cli/main.py
index a1c7226..b8cb918 100755
--- a/cli/main.py
+++ b/cli/main.py
@@ -274,6 +274,12 @@
         from pdb import set_trace
         set_trace()
 
+    def do_version(self, line):
+        """Show the VOLTHA core version"""
+        stub = self.get_stub()
+        voltha = stub.GetVoltha(Empty())
+        self.poutput('{}'.format(voltha.version))
+
     def do_health(self, line):
         """Show connectivity status to Voltha status"""
         stub = voltha_pb2.HealthServiceStub(self.get_channel())
diff --git a/requirements.txt b/requirements.txt
index d455022..39e89a8 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -57,6 +57,8 @@
 xmltodict==0.11.0
 dicttoxml==1.7.4
 etcd3==0.7.0
+pyparsing==2.2.0
+packaging==17.1
 
 # python-consul>=0.6.1  we need the pre-released version for now, because 0.6.1 does not
 # yet support Twisted. Once this is released, it will be the 0.6.2 version
@@ -64,4 +66,3 @@
 
 # Twisted Python kafka client
 git+https://github.com/ciena/afkak.git
-
diff --git a/voltha/VERSION b/voltha/VERSION
new file mode 100644
index 0000000..c3f0d2b
--- /dev/null
+++ b/voltha/VERSION
@@ -0,0 +1 @@
+1.4.0-dev
diff --git a/voltha/main.py b/voltha/main.py
index c19a018..36c6013 100755
--- a/voltha/main.py
+++ b/voltha/main.py
@@ -46,11 +46,11 @@
 from voltha.protos.common_pb2 import LogLevel
 from voltha.registry import registry, IComponent
 from common.frameio.frameio import FrameIOManager
-
-VERSION = '0.9.0'
+from packaging.version import Version
 
 
 defs = dict(
+    version_file='./VERSION',
     config=os.environ.get('CONFIG', './voltha.yml'),
     container_name_regex=os.environ.get('CORE_NUMBER_EXTRACTOR', '^.*\.([0-9]+)\..*$'),
     consul=os.environ.get('CONSUL', 'localhost:8500'),
@@ -238,9 +238,9 @@
     if args.instance_id_is_container_name:
         args.instance_id = get_my_containers_name()
 
-    """ 
-    The container external, internal IP and PON interface needs to be 
-    set based on the subnet data.  At this time the internal IP is not used. 
+    """
+    The container external, internal IP and PON interface needs to be
+    set based on the subnet data.  At this time the internal IP is not used.
     The external IP is used for inter-core communications.  If the subnets are
     set then they take precedence over the other relevant arguments (
     external and internal host as well as interface
@@ -290,6 +290,9 @@
                                  verbosity_adjust=verbosity_adjust)
         self.log.info('core-number-extractor', regex=args.container_name_regex)
 
+        self.voltha_version = self.get_version()
+        self.log.info('VOLTHA version is {}'.format(self.voltha_version))
+
         # configurable variables from voltha.yml file
         #self.configurable_vars = self.config.get('Constants', {})
 
@@ -313,6 +316,23 @@
 
         self.manhole = None
 
+    def get_version(self):
+        path = defs['version_file']
+        if not path.startswith('/'):
+            dir = os.path.dirname(os.path.abspath(__file__))
+            path = os.path.join(dir, path)
+
+        path = os.path.abspath(path)
+        version_file = open(path, 'r')
+        v = version_file.read()
+
+        # Use Version to validate the version string - exception will be raised
+        # if the version is invalid
+        Version(v)
+
+        version_file.close()
+        return v
+
     def start(self):
         self.start_reactor()  # will not return except Keyboard interrupt
 
@@ -387,7 +407,7 @@
                     instance_id=self.instance_id,
                     core_store_id = self.core_store_id,
                     grpc_port=self.args.grpc_port,
-                    version=VERSION,
+                    version=self.voltha_version,
                     log_level=LogLevel.INFO
                 )
             ).start(config_backend=load_backend(store_id=self.core_store_id,