Skeleton and sensors works
diff --git a/wally/node_interfaces.py b/wally/node_interfaces.py
index bc9ba28..8552a3d 100644
--- a/wally/node_interfaces.py
+++ b/wally/node_interfaces.py
@@ -9,7 +9,7 @@
 
 class NodeInfo:
     """Node information object, result of discovery process or config parsing"""
-    def __init__(self, ssh_creds: ConnCreds, roles: Set[str]) -> None:
+    def __init__(self, ssh_creds: ConnCreds, roles: Set[str], params: Dict[str, Any] = None) -> None:
 
         # ssh credentials
         self.ssh_creds = ssh_creds
@@ -18,10 +18,18 @@
         self.roles = roles
         self.os_vm_id = None  # type: Optional[int]
         self.params = {}  # type: Dict[str, Any]
+        if params is not None:
+            self.params = params
 
     def node_id(self) -> str:
         return "{0.host}:{0.port}".format(self.ssh_creds.addr)
 
+    def __str__(self) -> str:
+        return self.node_id()
+
+    def __repr__(self) -> str:
+        return str(self)
+
 
 class ISSHHost(metaclass=abc.ABCMeta):
     """Minimal interface, required to setup RPC connection"""
@@ -55,6 +63,7 @@
     """Remote filesystem interface"""
     info = None  # type: NodeInfo
     conn = None  # type: Any
+    rpc_log_file = None  # type: str
 
     @abc.abstractmethod
     def run(self, cmd: str, timeout: int = 60, nolog: bool = False) -> str:
@@ -84,6 +93,10 @@
     def disconnect(self) -> str:
         pass
 
+    @abc.abstractmethod
+    def upload_plugin(self, name: str, code: bytes, version: str = None) -> None:
+        pass
+
     def __enter__(self) -> 'IRPCNode':
         return self