1
2 """
3 Library for managing user sessions.
4
5 Copyright 2010 Glencoe Software, Inc. All rights reserved.
6 Use is subject to license terms supplied in LICENSE.txt
7
8 """
9
10 """
11 * Track last used
12 * provide single library (with lock) which does all of this
13 - save session
14 - clear session
15 - check session # detachOnDestroy
16 - list previous sessions
17 * Use an environment variable for changing directories
18
19 import subprocess, optparse, os, sys
20 import getpass, pickle
21 import omero.java
22 from omero.cli import Arguments, BaseControl, VERSION
23 from path import path
24
25 """
26
27 from omero.util import get_user_dir, make_logname
28 from path import path
29
30 import logging
31 import exceptions
32
33
35 """
36 The store is a file-based repository of user sessions.
37 By default, stores use $HOME/omero/sessions as their
38 repository path.
39
40 Use add() to add items to the repository
41 """
42
44 """
45 """
46 self.logger = logging.getLogger(make_logname(self))
47 if dir == None:
48 dir = get_user_dir()
49 self.dir = path(dir) / "omero" / "sessions"
50 if not self.dir.exists():
51 self.dir.makedirs()
52 try:
53 self.dir.chmod(0700)
54 except:
55 print "WARN: failed to chmod %s" % self.dir
56
57
58
59
60
62 """
63 Simple dump utility
64 """
65 for host in self.dir.dirs():
66 print "[%s]" % host
67 for name in host.dirs():
68 print " -> %s : " % name
69 for sess in name.files():
70 print " %s" % sess
71
72 - def add(self, host, name, id, props):
73 """
74 Stores a file containing the properties at
75 REPO/host/name/id
76 """
77
78 props["omero.host"] = host
79 props["omero.user"] = name
80 props["omero.sess"] = id
81
82 lines = []
83 for k,v in props.items():
84 lines.append("%s=%s" % (k, v))
85
86 dhn = self.dir / host / name
87 if not dhn.exists():
88 dhn.makedirs()
89
90 (dhn / id).write_lines(lines)
91
92 - def conflicts(self, host, name, id, new_props, ignore_nulls = False):
93 """
94 Compares if the passed properties are compatible with
95 with those for the host, name, id tuple
96
97 If ignore_nulls is True, then a null in new_props means matches
98 anything.
99 """
100 conflicts = ""
101 old_props = self.get(host, name, id)
102 for key in ("omero.group", "omero.port"):
103 old = old_props.get(key, None)
104 new = new_props.get(key, None)
105 if ignore_nulls and new is None:
106 continue
107 elif old != new:
108 conflicts += (key + (":%s!=%s;" % (old, new)))
109 return conflicts
110
111 - def remove(self, host, name, uuid):
112 """
113 Removes the given session file from the store
114 and removes the sess_file() if it is equal to
115 the session we just removed.
116 """
117 if uuid is None:
118 self.logger.debug("No uuid provided")
119 return
120 d = self.dir / host / name
121 f = self.dir / host / name / uuid
122 if d.exists():
123 if f.exists():
124 f.remove()
125 self.logger.debug("Removed %s" % f)
126 s = self.sess_file(host, name)
127 if s and s.exists() and s.text().strip() == uuid:
128 s.remove()
129 self.logger.debug("Removed %s" % s)
130
131 - def exists(self, host, name, uuid):
132 """
133 Checks if the given file exists.
134 """
135 d = self.dir
136 for x in (host, name, uuid):
137 d = d / x
138 if not d.exists():
139 return False
140 return True
141
142 - def get(self, host, name, uuid):
143 """
144 Returns the properties stored in the given session file
145 """
146 return self.props(self.dir / host / name / uuid)
147
149 """
150 Returns the path to property files which are stored.
151 Internal accounting files are not returned.
152 """
153 d = self.dir / host / name
154 if not d.exists():
155 return []
156 return [x.basename() for x in self.non_dot(d)]
157
158 - def set_current(self, host, name = None, uuid = None):
159 """
160 Sets the current session, user, and host files
161 These are used as defaults by other methods.
162 """
163 if host is not None: self.host_file().write_text(host)
164 if name is not None: self.user_file(host).write_text(name)
165 if uuid is not None: self.sess_file(host, name).write_text(uuid)
166
184
186 """
187 Prints either the last saved host (see get_current())
188 or "localhost"
189 """
190 f = self.host_file()
191 if not f.exists():
192 return "localhost"
193 text = f.text().strip()
194 if not text:
195 return "localhost"
196 return text
197
199 """
200 Returns the name of a user for which the
201 session key exists. This value is taken
202 from the path rather than from the properties
203 file since that value may have been overwritten.
204 An exception is raised if there is more than one
205 name since keys should be UUIDs. A None may be
206 returned.
207 """
208 s = self.dir / server
209 if not s.exists():
210 return None
211 else:
212 n = [x.basename() for x in s.dirs() if (x/uuid).exists()]
213 if not n:
214 return None
215 elif len(n) == 1:
216 return n[0]
217 else:
218 raise exceptions.Exception("Multiple names found for uuid=%s: %s" % (uuid, ", ".join(n)))
219
220 - def contents(self):
221 """
222 Returns a map of maps with all the contents
223 of the store. Internal accounting files are
224 skipped.
225 """
226 rv = {}
227 Dhosts = self.dir.dirs()
228 for Dhost in Dhosts:
229 host = str(Dhost.basename())
230 if host not in rv:
231 rv[host] = {}
232 Dnames = Dhost.dirs()
233 for Dname in Dnames:
234 name = str(Dname.basename())
235 if name not in rv[host]:
236 rv[host][name] = {}
237 Dids = self.non_dot(Dname)
238 for Did in Dids:
239 id = str(Did.basename())
240 props = self.props(Did)
241 props["active"] = "unknown"
242 rv[host][name][id] = props
243 return rv
244
245 - def count(self, host=None, name=None):
246 """
247 Returns the sum of all files visited by walk()
248 """
249 def f(h, n, s):
250 f.i += 1
251 f.i = 0
252 self.walk(f, host, name)
253 return f.i
254
255 - def walk(self, func, host=None, name=None, sess=None):
256 """
257 Applies func to all host, name, and session path-objects.
258 """
259 for h in self.dir.dirs():
260 if host is None or str(h.basename()) == host:
261 for n in h.dirs():
262 if name is None or str(n.basename()) == name:
263 for s in self.non_dot(n):
264 if sess is None or str(s.basename()) == sess:
265 func(h, n, s)
266
267
268
269
270
271
272 - def attach(self, server, name, sess, set_current = True):
273 """
274 Simple helper. Delegates to create() using the session
275 as both the username and the password. This reproduces
276 the logic of client.joinSession()
277 """
278 props = self.get(server, name, sess)
279 return self.create(sess, sess, props, new = False, set_current = set_current)
280
281 - def create(self, name, pasw, props, new = True, set_current = True):
282 """
283 Creates a new omero.client object, and returns:
284 (cilent, session_id, timeToIdle, timeToLive)
285 """
286 import omero.clients
287 props = dict(props)
288 host = props["omero.host"]
289 client = omero.client(props)
290 client.setAgent("OMERO.sessions")
291 sf = client.createSession(name, pasw)
292 ec = sf.getAdminService().getEventContext()
293 uuid = sf.ice_getIdentity().name
294 sf.detachOnDestroy()
295 sess = sf.getSessionService().getSession(uuid)
296 timeToIdle = sess.getTimeToIdle().getValue()
297 timeToLive = sess.getTimeToLive().getValue()
298 if new:
299 self.add(host, ec.userName, uuid, props)
300 if set_current:
301 self.set_current(host, ec.userName, uuid)
302
303 return client, uuid, timeToIdle, timeToLive
304
305 - def clear(self, host = None, name = None, sess = None):
306 """
307 Walks through all sessions and calls killSession.
308 Regardless of exceptions, it will remove the session files
309 from the store.
310 """
311 removed = []
312 def f(h, n, s):
313 hS = str(h.basename())
314 nS = str(n.basename())
315 sS = str(s.basename())
316 try:
317 client = self.attach(hS, nS, sS)
318 client.killSession()
319 except exceptions.Exception, e:
320 self.logger.debug("Exception on killSession: %s" % e)
321 s.remove()
322 removed.append(s)
323 self.walk(f, host, name, sess)
324 return removed
325
326
327
328
329
331 """ Returns the path-object which stores the last active host """
332 return self.dir / "._LASTHOST_"
333
335 """ Returns the path-object which stores the last active user """
336 d = self.dir / host
337 if not d.exists():
338 d.makedirs()
339 return d / "._LASTUSER_"
340
342 """ Returns the path-object which stores the last active session """
343 d = self.dir / host / user
344 if not d.exists():
345 d.makedirs()
346 return d / "._LASTSESS_"
347
349 """ Only returns the files (not directories) contained in d that don't start with a dot """
350 return [f for f in d.files("*") if not str(f.basename()).startswith(".")]
351
353 """
354 Parses the path-object into properties
355 """
356 txt = f.text()
357 lines = txt.split("\n")
358 props = {}
359 for line in lines:
360 if not line:
361 continue
362 parts = line.split("=",1)
363 if len(parts) == 1:
364 parts.append("")
365 props[parts[0]] = parts[1]
366 return props
367
368 if __name__ == "__main__":
369 SessionsStore().report()
370