and on
[playground.git] / omf_keys / key_fs.py
index 80cdc42..6993435 100644 (file)
@@ -3,21 +3,93 @@
 # A FUSE filesystem implementation to provide a file interface for
 # vsys_publickeys VSYS script. To be used by OMF Resource Controller.
 
+# Usage: ./keys_fs.py /keys
+#        ls /keys
+#        cat /keys/all
+
+# NOTE:
+# Sliver has to have following ccapabilities set.
+# SECURE_MOUNT
+# BINARY_MOUNT
+#
+# we also depend on fuse and python-fuse packages.
+#
+
+
 import os
+import sys
 import stat
 import errno
 import fuse
-import sys
+import fcntl
+import select
 from fuse import Fuse
 
 fuse.fuse_python_api = (0, 2)
 
 keys_dir = "/keys"
-keys_file = os.path.join(keys_dir, "all")
+all_ssh_keys = None
+all_ssh_keys_dict = None
 
-# TODO: for Giovanni
 def read_keys():
-    return "reading PLC users' public keys\n"
+    global all_ssh_keys
+    if all_ssh_keys:
+        return all_ssh_keys
+        
+    fin = os.open("/vsys/publickeys.in", os.O_NONBLOCK | os.O_WRONLY)
+    fout = os.open("/vsys/publickeys.out", os.O_NONBLOCK | os.O_RDONLY)
+    
+    in_flags = fcntl.fcntl(fin, fcntl.F_GETFL)
+    out_flags = fcntl.fcntl(fin, fcntl.F_GETFL)
+    
+    res = select.select([fout], [], [])
+    
+    fcntl.fcntl(fin, fcntl.F_SETFL, in_flags & ~os.O_NONBLOCK)
+    fcntl.fcntl(fout, fcntl.F_SETFL, out_flags & ~os.O_NONBLOCK)
+    
+    f = os.fdopen(fout, "r")
+    all_ssh_keys = f.read()
+    return all_ssh_keys
+
+
+def all_keys():
+    global all_ssh_keys_dict
+    if all_ssh_keys_dict:
+        return all_ssh_keys_dict
+
+    keys = read_keys()
+    files = {}
+    num = 0
+    for line in keys.split('\n'):
+        line = line.strip()
+        if not line: continue
+
+        filename = ""
+        in_key = False
+        in_name = False
+        fields = line.split()
+        for f in fields:
+            f = f.strip()
+            if f.startswith("ssh-"):
+                in_key = True
+                continue
+            elif in_key:
+                in_name = True
+                in_key = False
+                continue
+            elif in_name:
+                if filename:
+                    filename = "%s_%s" % (filename, f)
+                else:
+                    filename = f
+
+        if not filename:
+            num += 1
+            files["unnamed_key%d" % num] = line
+        else:
+            files[filename] = "%s\n" % line
+
+    return files
 
 class MyStat(fuse.Stat):
     def __init__(self):
@@ -42,14 +114,26 @@ class KeyFS(Fuse):
         if path == '/':
             st.st_mode = stat.S_IFDIR | 0755
             st.st_nlink = 2
-        else:
+        elif os.path.basename(path) == "all":
             st.st_mode = stat.S_IFREG | 0444
             st.st_nlink = 1
             st.st_size = len(read_keys())
+        else:
+            filename = os.path.basename(path)
+            keys = all_keys()
+            st.st_mode = stat.S_IFREG | 0444
+            st.st_nlink = 1
+            try:
+                st.st_size = len(keys[filename])
+            except:
+                st.st_size = 0
         return st
 
     def readdir(self, path, offset):
-        for r in  '.', '..', os.path.basename(keys_file):
+        files = ['.', '..', "all"]
+        keys = all_keys()
+        files.extend(keys.keys())
+        for r in files:
             yield fuse.Direntry(r)
 
     def open(self, path, flags):
@@ -58,13 +142,19 @@ class KeyFS(Fuse):
             return -errno.EACCES
 
     def read (self, path, size, offset):
-        keys = read_keys()
-        slen = len(keys)
+        if os.path.basename(path) == "all":
+            content = read_keys()
+        else:
+            filename = os.path.basename(path)
+            keys = all_keys()
+            content = keys[filename]
+
+        slen = len(content)
 
         if offset < slen:
             if offset + size > slen:
                 size = slen - offset
-            buf = keys[offset:offset+size]
+            buf = content[offset:offset+size]
         else:
             buf = ''
         return buf