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_server.py b/netconf/nc_server.py
index 3b22290..6c43194 100644
--- a/netconf/nc_server.py
+++ b/netconf/nc_server.py
@@ -16,6 +16,7 @@
 
 import structlog
 import sys
+import os
 from twisted.conch import avatar
 from twisted.cred import portal
 from twisted.conch.checkers import SSHPublicKeyChecker, InMemorySSHKeyDB
@@ -32,6 +33,7 @@
 from session.session_mgr import get_session_manager_instance
 from constants import Constants as C
 
+dir_path = os.path.dirname(os.path.realpath(__file__))
 
 # logp.startLogging(sys.stderr)
 
@@ -40,17 +42,17 @@
 
 # @implementer(conchinterfaces.ISession)
 class NetconfAvatar(avatar.ConchUser):
-    def __init__(self, username, nc_server, grpc_stub):
+    def __init__(self, username, nc_server, grpc_client):
         avatar.ConchUser.__init__(self)
         self.username = username
         self.nc_server = nc_server
-        self.grpc_stub = grpc_stub
+        self.grpc_client = grpc_client
         self.channelLookup.update({'session': session.SSHSession})
         self.subsystemLookup.update(
             {b"netconf": NetconfConnection})
 
-    def get_grpc_stub(self):
-        return self.grpc_stub
+    def get_grpc_client(self):
+        return self.grpc_client
 
     def get_nc_server(self):
         return self.nc_server
@@ -64,12 +66,12 @@
 
 @implementer(portal.IRealm)
 class NetconfRealm(object):
-    def __init__(self, nc_server, grpc_stub):
-        self.grpc_stub = grpc_stub
+    def __init__(self, nc_server, grpc_client):
+        self.grpc_client = grpc_client
         self.nc_server = nc_server
 
     def requestAvatar(self, avatarId, mind, *interfaces):
-        user = NetconfAvatar(avatarId, self.nc_server, self.grpc_stub)
+        user = NetconfAvatar(avatarId, self.nc_server, self.grpc_client)
         return interfaces[0], user, user.logout
 
 
@@ -86,7 +88,7 @@
                  server_public_key_file,
                  client_public_keys_file,
                  client_passwords_file,
-                 grpc_stub):
+                 grpc_client):
 
         self.netconf_port = netconf_port
         self.server_private_key_file = server_private_key_file
@@ -94,7 +96,7 @@
         self.client_public_keys_file = client_public_keys_file
         self.client_passwords_file = client_passwords_file
         self.session_mgr = get_session_manager_instance()
-        self.grpc_stub = grpc_stub
+        self.grpc_client = grpc_client
         self.connector = None
         self.nc_client_map = {}
         self.running = False
@@ -116,6 +118,12 @@
         self.d_stopped.callback(None)
         log.info('stopped')
 
+    def reload_capabilities(self):
+        # TODO: Called when there is a reconnect to voltha
+        # If there are new device types then the new
+        # capabilities will be exposed for subsequent client connections to use
+        pass
+
     def client_disconnected(self, result, handler, reason):
         assert isinstance(handler, NetconfProtocolHandler)
 
@@ -131,30 +139,33 @@
         #create a session
         session = self.session_mgr.create_session(client_conn.avatar.get_user())
         handler = NetconfProtocolHandler(self, client_conn,
-                                         session, self.grpc_stub)
+                                         session, self.grpc_client)
         client_conn.proto_handler = handler
         reactor.callLater(0, handler.start)
 
     def setup_secure_access(self):
         try:
             from twisted.cred import portal
-            portal = portal.Portal(NetconfRealm(self, self.grpc_stub))
+            portal = portal.Portal(NetconfRealm(self, self.grpc_client))
 
             # setup userid-password access
-            password_file = '{}/{}'.format(C.CLIENT_CRED_DIRECTORY,
-                                           self.client_passwords_file)
+            password_file = '{}/{}/{}'.format(dir_path,
+                                              C.CLIENT_CRED_DIRECTORY,
+                                              self.client_passwords_file)
             portal.registerChecker(FilePasswordDB(password_file))
 
             # setup access when client uses keys
-            keys_file = '{}/{}'.format(C.CLIENT_CRED_DIRECTORY,
-                                       self.client_public_keys_file)
+            keys_file = '{}/{}/{}'.format(dir_path,
+                                          C.CLIENT_CRED_DIRECTORY,
+                                          self.client_public_keys_file)
             with open(keys_file) as f:
                 users = [line.rstrip('\n') for line in f]
             users_dict = {}
             for user in users:
                 users_dict[user.split(':')[0]] = [
-                    keys.Key.fromFile('{}/{}'.format(C.CLIENT_CRED_DIRECTORY,
-                                                     user.split(':')[1]))]
+                    keys.Key.fromFile('{}/{}/{}'.format(dir_path,
+                                                        C.CLIENT_CRED_DIRECTORY,
+                                                        user.split(':')[1]))]
             sshDB = SSHPublicKeyChecker(InMemorySSHKeyDB(users_dict))
             portal.registerChecker(sshDB)
             return portal
@@ -182,8 +193,9 @@
         return SSHServerTransport()
 
     def getPublicKeys(self):
-        key_file_name = '{}/{}'.format(C.KEYS_DIRECTORY,
-                                       self.server_public_key_file)
+        key_file_name = '{}/{}/{}'.format(dir_path,
+                                          C.KEYS_DIRECTORY,
+                                          self.server_public_key_file)
         try:
             publicKeys = {
                 'ssh-rsa': keys.Key.fromFile(key_file_name)
@@ -194,8 +206,9 @@
                       filename=key_file_name, exception=repr(e))
 
     def getPrivateKeys(self):
-        key_file_name = '{}/{}'.format(C.KEYS_DIRECTORY,
-                                       self.server_private_key_file)
+        key_file_name = '{}/{}/{}'.format(dir_path,
+                                          C.KEYS_DIRECTORY,
+                                          self.server_private_key_file)
         try:
             privateKeys = {
                 'ssh-rsa': keys.Key.fromFile(key_file_name)