This commit consists of:
1) Dockerizing the netconf server
2) Update proto2yang to support module imports
3) Provide a set of yang modules derived from the proto files in voltha.
   These files as well as the slight mmodifications to the proto files are
   provided in the experiments/netconf/proto2yang directory
4) Code to automatically pull proto files from voltha into the netconf server,
   compiles them and produce the yang equivalent files.
5) Add a getvoltha netconf API to provide voltha state information (basic at
   this time).  There is potential to make this generic once we experiment
   with additional APIs

Change-Id: I94f3a1f871b8025ad675d5f9b9b626d1be8b8d36
diff --git a/netconf/nc_rpc/base/close_session.py b/netconf/nc_rpc/base/close_session.py
index 43babb8..ce187cd 100644
--- a/netconf/nc_rpc/base/close_session.py
+++ b/netconf/nc_rpc/base/close_session.py
@@ -24,8 +24,9 @@
 
 class CloseSession(Rpc):
 
-    def __init__(self, rpc_request, rpc_method, session):
-        super(CloseSession, self).__init__(rpc_request, rpc_method, session)
+    def __init__(self, rpc_request, rpc_method, grpc_client, session):
+        super(CloseSession, self).__init__(rpc_request, rpc_method,
+                                           grpc_client, session)
         self._validate_parameters()
 
     def execute(self):
diff --git a/netconf/nc_rpc/base/commit.py b/netconf/nc_rpc/base/commit.py
index 61b7604..8933dc3 100644
--- a/netconf/nc_rpc/base/commit.py
+++ b/netconf/nc_rpc/base/commit.py
@@ -24,8 +24,9 @@
 
 class Commit(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(Commit, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(Commit, self).__init__(rpc_request, rpc_method, grpc_client,
+									 session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/base/copy_config.py b/netconf/nc_rpc/base/copy_config.py
index cf2fc82..e287770 100644
--- a/netconf/nc_rpc/base/copy_config.py
+++ b/netconf/nc_rpc/base/copy_config.py
@@ -23,8 +23,9 @@
 
 class CopyConfig(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(CopyConfig, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(CopyConfig, self).__init__(rpc_request, rpc_method,
+										 grpc_client, session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/base/delete_config.py b/netconf/nc_rpc/base/delete_config.py
index 7163ee6..e267807 100644
--- a/netconf/nc_rpc/base/delete_config.py
+++ b/netconf/nc_rpc/base/delete_config.py
@@ -23,8 +23,9 @@
 
 class DeleteConfig(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(DeleteConfig, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(DeleteConfig, self).__init__(rpc_request, rpc_method,
+										   grpc_client, session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/base/discard_changes.py b/netconf/nc_rpc/base/discard_changes.py
index c41d32e..57bdfed 100644
--- a/netconf/nc_rpc/base/discard_changes.py
+++ b/netconf/nc_rpc/base/discard_changes.py
@@ -23,8 +23,9 @@
 
 class DiscardChanges(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(DiscardChanges, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(DiscardChanges, self).__init__(rpc_request, rpc_method,
+											 grpc_client, session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/base/edit_config.py b/netconf/nc_rpc/base/edit_config.py
index 5c7599a..469e957 100644
--- a/netconf/nc_rpc/base/edit_config.py
+++ b/netconf/nc_rpc/base/edit_config.py
@@ -23,8 +23,9 @@
 
 class EditConfig(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(EditConfig, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(EditConfig, self).__init__(rpc_request, rpc_method,
+										 grpc_client, session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/base/get.py b/netconf/nc_rpc/base/get.py
index c6cdfab..39e095c 100644
--- a/netconf/nc_rpc/base/get.py
+++ b/netconf/nc_rpc/base/get.py
@@ -25,8 +25,9 @@
 
 class Get(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(Get, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(Get, self).__init__(rpc_request, rpc_method, grpc_client,
+								  session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/base/get_config.py b/netconf/nc_rpc/base/get_config.py
index dffe0d6..09f90b4 100644
--- a/netconf/nc_rpc/base/get_config.py
+++ b/netconf/nc_rpc/base/get_config.py
@@ -26,8 +26,9 @@
 
 class GetConfig(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(GetConfig, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(GetConfig, self).__init__(rpc_request, rpc_method,
+										grpc_client, session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/base/kill_session.py b/netconf/nc_rpc/base/kill_session.py
index 08a2e7a..c9a3352 100644
--- a/netconf/nc_rpc/base/kill_session.py
+++ b/netconf/nc_rpc/base/kill_session.py
@@ -25,8 +25,9 @@
 
 class KillSession(Rpc):
 
-    def __init__(self, rpc_request, rpc_method, session):
-        super(KillSession, self).__init__(rpc_request, rpc_method, session)
+    def __init__(self, rpc_request, rpc_method, grpc_client, session):
+        super(KillSession, self).__init__(rpc_request, rpc_method,
+                                          grpc_client, session)
         self._validate_parameters()
 
     def execute(self):
diff --git a/netconf/nc_rpc/base/lock.py b/netconf/nc_rpc/base/lock.py
index fc74e83..2f0130d 100644
--- a/netconf/nc_rpc/base/lock.py
+++ b/netconf/nc_rpc/base/lock.py
@@ -23,8 +23,9 @@
 
 class Lock(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(Lock, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(Lock, self).__init__(rpc_request, rpc_method, grpc_client,
+								   session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/base/unlock.py b/netconf/nc_rpc/base/unlock.py
index 78c59f1..f9ef062 100644
--- a/netconf/nc_rpc/base/unlock.py
+++ b/netconf/nc_rpc/base/unlock.py
@@ -23,8 +23,9 @@
 
 class UnLock(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(UnLock, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(UnLock, self).__init__(rpc_request, rpc_method, grpc_client,
+									 session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/base/validate.py b/netconf/nc_rpc/base/validate.py
index 1cb84af..93faf60 100644
--- a/netconf/nc_rpc/base/validate.py
+++ b/netconf/nc_rpc/base/validate.py
@@ -23,8 +23,9 @@
 
 class Validate(Rpc):
 
-	def __init__(self, rpc_request, rpc_method, session):
-		super(Validate, self).__init__(rpc_request, rpc_method, session)
+	def __init__(self, rpc_request, rpc_method, grpc_client, session):
+		super(Validate, self).__init__(rpc_request, rpc_method,
+									   grpc_client, session)
 		self._validate_parameters()
 
 	def execute(self):
diff --git a/netconf/nc_rpc/ext/__init__.py b/netconf/nc_rpc/ext/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/netconf/nc_rpc/ext/__init__.py
diff --git a/netconf/nc_rpc/ext/get_voltha.py b/netconf/nc_rpc/ext/get_voltha.py
new file mode 100644
index 0000000..a619875
--- /dev/null
+++ b/netconf/nc_rpc/ext/get_voltha.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+# Copyright 2016 the original author or authors.
+#
+# 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.
+#
+from lxml import etree
+import structlog
+from netconf.nc_rpc.rpc import Rpc
+import netconf.nc_common.error as ncerror
+from netconf.constants import Constants as C
+from netconf.utils import filter_tag_match
+from twisted.internet.defer import inlineCallbacks, returnValue
+import dicttoxml
+from simplejson import dumps, load
+
+log = structlog.get_logger()
+
+
+class GetVoltha(Rpc):
+    def __init__(self, rpc_request, rpc_method, grpc_client, session):
+        super(GetVoltha, self).__init__(rpc_request, rpc_method,
+                                        grpc_client, session)
+        self._validate_parameters()
+
+    @inlineCallbacks
+    def execute(self):
+        log.info('get-voltha-request', session=self.session.session_id)
+        if self.rpc_response.is_error:
+            returnValue(self.rpc_response)
+
+        # Invoke voltha via the grpc client
+        res_dict = yield self.grpc_client.get_voltha_instance()
+
+        # convert dict to xml
+        xml = dicttoxml.dicttoxml(res_dict)
+        log.info('voltha-info', res=res_dict, xml=xml)
+
+        self.rpc_response.node = self.get_root_element(xml)
+        self.rpc_response.is_error = False
+
+        returnValue(self.rpc_response)
+
+
+    def _validate_parameters(self):
+        log.info('validate-parameters', session=self.session.session_id)
+        self.params = self.rpc_method.getchildren()
+        if len(self.params) > 1:
+            self.rpc_response.is_error = True
+            self.rpc_response.node = ncerror.BadMsg(self.rpc_request)
+            return
+
+        if self.params and not filter_tag_match(self.params[0], C.NC_FILTER):
+            self.rpc_response.is_error = True
+            self.rpc_response.node = ncerror.UnknownElement(
+                self.rpc_request, self.params[0])
+            return
+
+        if not self.params:
+            self.params = [None]
diff --git a/netconf/nc_rpc/rpc.py b/netconf/nc_rpc/rpc.py
index 3dd2f17..ff9b303 100644
--- a/netconf/nc_rpc/rpc.py
+++ b/netconf/nc_rpc/rpc.py
@@ -18,12 +18,15 @@
 #
 
 from  rpc_response import RpcResponse
+from lxml import etree
+import io
 
 class Rpc(object):
-    def __init__(self,rpc_request, rpc_method, session):
+    def __init__(self,rpc_request, rpc_method, grpc_client, session):
         self.rpc_request = rpc_request
         self.rpc_method = rpc_method
         self.rpc_response = RpcResponse()
+        self.grpc_client =  grpc_client
         self.session = session
 
     def execute(self):
@@ -36,3 +39,8 @@
     def _validate_parameters(self, rpc_request):
         """Sets and validates the node as well"""
         pass
+
+    def get_root_element(self, xml_msg):
+        tree = etree.parse(io.BytesIO(xml_msg))
+        return tree.getroot()
+
diff --git a/netconf/nc_rpc/rpc_factory.py b/netconf/nc_rpc/rpc_factory.py
index f3ec0cc..eb13b8d 100644
--- a/netconf/nc_rpc/rpc_factory.py
+++ b/netconf/nc_rpc/rpc_factory.py
@@ -28,6 +28,7 @@
 from base.unlock import UnLock
 from base.close_session import CloseSession
 from base.kill_session import KillSession
+from ext.get_voltha import GetVoltha
 from netconf import NSMAP, qmap
 import netconf.nc_common.error as ncerror
 log = structlog.get_logger()
@@ -36,7 +37,7 @@
 
 	instance = None
 
-	def get_rpc_handler(self, rpc_node, msg, session):
+	def get_rpc_handler(self, rpc_node, msg, grpc_channel, session):
 		try:
 			msg_id = rpc_node.get('message-id')
 			log.info("Received-rpc-message-id", msg_id=msg_id)
@@ -59,12 +60,13 @@
 
 		class_handler = self.rpc_class_handlers.get(rpc_name, None)
 		if class_handler is not None:
-			return class_handler(rpc_node, rpc_method, session)
+			return class_handler(rpc_node, rpc_method, grpc_channel, session)
 
 		log.error("rpc-not-implemented", rpc=rpc_name)
 
 
 	rpc_class_handlers = {
+		'getvoltha' : GetVoltha,
 		'get-config': GetConfig,
 		'get': Get,
 		'edit-config': EditConfig,
@@ -83,3 +85,8 @@
 		RpcFactory.instance = RpcFactory()
 	return RpcFactory.instance
 
+
+if __name__ == '__main__':
+   fac = get_rpc_factory_instance()
+   rpc = fac.rpc_class_handlers.get('getvoltha', None)
+   print rpc(None,None,None)
\ No newline at end of file