e3deadcf9724c860c92458fd75d789e4cad898e5
[playground.git] / omf_keys / key_fs.py
1 #!/usr/bin/python
2
3 # A FUSE filesystem implementation to provide a file interface for
4 # vsys_publickeys VSYS script. To be used by OMF Resource Controller.
5
6 # Usage: ./keys_fs.py /keys
7 #        ls /keys
8 #        cat /keys/all
9
10 # NOTE:
11 # Sliver has to have following ccapabilities set.
12 # SECURE_MOUNT
13 # BINARY_MOUNT
14 #
15 # we also depend on fuse and python-fuse packages.
16 #
17
18
19 import os
20 import sys
21 import stat
22 import errno
23 import fuse
24 import fcntl
25 import select
26 from fuse import Fuse
27
28 fuse.fuse_python_api = (0, 2)
29
30 keys_dir = "/keys"
31
32
33 def read_keys():
34     fin = os.open("/vsys/publickeys.in", os.O_NONBLOCK | os.O_WRONLY)
35     fout = os.open("/vsys/publickeys.out", os.O_NONBLOCK | os.O_RDONLY)
36     
37     in_flags = fcntl.fcntl(fin, fcntl.F_GETFL)
38     out_flags = fcntl.fcntl(fin, fcntl.F_GETFL)
39     
40     res = select.select([fout], [], [])
41     
42     fcntl.fcntl(fin, fcntl.F_SETFL, in_flags & ~os.O_NONBLOCK)
43     fcntl.fcntl(fout, fcntl.F_SETFL, out_flags & ~os.O_NONBLOCK)
44     
45     f = os.fdopen(fout, "r")
46     return f.read()
47
48 def all_keys():
49     keys = read_keys()
50
51     files = {}
52     num = 0
53     for line in keys.split('\n'):
54         line = line.strip()
55         fields = line.split()
56         try:
57             name = fields[2]
58             files[name] = line
59         except:
60             num += 1
61             files["unnamed_key%d" % num] = line
62
63     return files
64
65 class MyStat(fuse.Stat):
66     def __init__(self):
67         self.st_mode = 0
68         self.st_ino = 0
69         self.st_dev = 0
70         self.st_nlink = 0
71         self.st_uid = 0
72         self.st_gid = 0
73         self.st_size = 0
74         self.st_atime = 0
75         self.st_mtime = 0
76         self.st_ctime = 0
77
78 class KeyFS(Fuse):
79
80     def __init__(self, *args, **kw):
81         Fuse.__init__(self, *args, **kw)
82
83     def getattr(self, path):
84         st = MyStat()
85         if path == '/':
86             st.st_mode = stat.S_IFDIR | 0755
87             st.st_nlink = 2
88         elif os.path.basename(path) == "all":
89             st.st_mode = stat.S_IFREG | 0444
90             st.st_nlink = 1
91             st.st_size = len(read_keys())
92         else:
93             filename = os.path.basename(path)
94             keys = all_keys()
95             st.st_mode = stat.S_IFREG | 0444
96             st.st_nlink = 1
97             try:
98                 st.st_size = len(keys[filename])
99             except:
100                 st.st_size = 0
101         return st
102
103     def readdir(self, path, offset):
104         files = ['.', '..', "all"]
105         keys = all_keys()
106         files.extend(keys.keys())
107         for r in files:
108             yield fuse.Direntry(r)
109
110     def open(self, path, flags):
111         accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
112         if (flags & accmode) != os.O_RDONLY:
113             return -errno.EACCES
114
115     def read (self, path, size, offset):
116         if os.path.basename(path) == "all":
117             content = read_keys()
118         else:
119             filename = os.path.basename(path)
120             keys = all_keys()
121             content = keys[filename]
122
123         slen = len(content)
124
125         if offset < slen:
126             if offset + size > slen:
127                 size = slen - offset
128             buf = keys[offset:offset+size]
129         else:
130             buf = ''
131         return buf
132
133
134
135 if __name__ == '__main__':
136     fs = KeyFS()
137     fs.multithreaded = 0
138     fs.parse(values=fs, errex=1)
139     try:
140         if fs.fuse_args.mount_expected():
141             os.chdir("/")
142     except OSError:
143         sys.stderr.write("can't enter root of underlying filesystem\n")
144         sys.exit(1)
145
146     fs.main()